Merge branch '2.4' into travis

pull/1722/head
Raphaël Vinot 2016-12-07 14:01:13 +01:00 committed by GitHub
commit 62c37bd6ef
39 changed files with 1608 additions and 168 deletions

2
.gitignore vendored
View File

@ -22,6 +22,8 @@
!/app/files/scripts/
!/app/files/warninglists
!/app/files/warninglists/*
!/app/files/misp-galaxy
!/app/files/misp-galaxy/*
/app/files/scripts/python-stix/
/app/files/scripts/python-cybox/
/app/files/scripts/*.pyc

3
.gitmodules vendored
View File

@ -18,3 +18,6 @@
path = app/Lib/random_compat
url = https://github.com/paragonie/random_compat
branch = master
[submodule "app/files/misp-galaxy"]
path = app/files/misp-galaxy
url = https://github.com/MISP/misp-galaxy

View File

@ -196,6 +196,86 @@ CREATE TABLE IF NOT EXISTS `feeds` (
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- -------------------------------------------------------
--
-- Table structure for `galaxies`
--
CREATE TABLE IF NOT EXISTS galaxies (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uuid` varchar(255) COLLATE utf8_bin NOT NULL,
`name` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT '',
`type` varchar(255) COLLATE utf8_bin NOT NULL,
`description` text COLLATE utf8_bin NOT NULL,
`version` varchar(255) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (id),
INDEX `name` (`name`),
INDEX `uuid` (`uuid`),
INDEX `type` (`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-- -------------------------------------------------------
--
-- Table structure for `galaxy_clusters`
--
CREATE TABLE IF NOT EXISTS galaxy_clusters (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uuid` varchar(255) COLLATE utf8_bin NOT NULL,
`type` varchar(255) COLLATE utf8_bin NOT NULL,
`value` text COLLATE utf8_bin NOT NULL,
`tag_name` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT '',
`description` text COLLATE utf8_bin NOT NULL,
`galaxy_id` int(11) NOT NULL,
`source` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT '',
`authors` text COLLATE utf8_bin NOT NULL,
PRIMARY KEY (id),
INDEX `value` (`value`(255)),
INDEX `uuid` (`uuid`),
INDEX `tag_name` (`tag_name`),
INDEX `type` (`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-- -------------------------------------------------------
--
-- Table structure for `galaxy_elements`
--
CREATE TABLE IF NOT EXISTS galaxy_elements (
`id` int(11) NOT NULL AUTO_INCREMENT,
`galaxy_cluster_id` int(11) NOT NULL,
`key` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT '',
`value` text COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`),
INDEX `key` (`key`),
INDEX `value` (`value`(255))
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-- -------------------------------------------------------
--
-- Table structure for `galaxy_reference`
--
CREATE TABLE IF NOT EXISTS galaxy_reference (
`id` int(11) NOT NULL AUTO_INCREMENT,
`galaxy_cluster_id` int(11) NOT NULL,
`referenced_galaxy_cluster_id` int(11) NOT NULL,
`referenced_galaxy_cluster_uuid` varchar(255) COLLATE utf8_bin NOT NULL,
`referenced_galaxy_cluster_type` text COLLATE utf8_bin NOT NULL,
`referenced_galaxy_cluster_value` text COLLATE utf8_bin NOT NULL,
PRIMARY KEY (id),
INDEX `galaxy_cluster_id` (`galaxy_cluster_id`),
INDEX `referenced_galaxy_cluster_id` (`referenced_galaxy_cluster_id`),
INDEX `referenced_galaxy_cluster_value` (`referenced_galaxy_cluster_value`(255)),
INDEX `referenced_galaxy_cluster_type` (`referenced_galaxy_cluster_type`(255))
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-- --------------------------------------------------------
--

View File

@ -1 +1 @@
{"major":2, "minor":4, "hotfix":55}
{"major":2, "minor":4, "hotfix":56}

View File

@ -107,6 +107,7 @@ class ServerShell extends AppShell
if ($timestamp != $task['Task']['next_execution_time']) {
return;
}
if ($task['Task']['timer'] > 0) $this->Task->reQueue($task, 'default', 'ServerShell', 'enqueuePull', $userId, $taskId);
$user = $this->User->getAuthUser($userId);
$servers = $this->Server->find('all', array('recursive' => -1, 'conditions' => array('pull' => 1)));
$count = count($servers);
@ -125,9 +126,6 @@ class ServerShell extends AppShell
);
$this->Job->save($data);
$jobId = $this->Job->id;
if ($task['Task']['timer'] > 0) $this->Task->reQueue($task, 'default', 'ServerShell', 'enqueuePull', $userId, $taskId);
App::uses('SyncTool', 'Tools');
$syncTool = new SyncTool();
$result = $this->Server->pull($user, $server['Server']['id'], 'full', $server, $jobId);

View File

@ -1519,7 +1519,7 @@ class AttributesController extends AppController {
// the last 4 fields accept the following operators:
// && - you can use && between two search values to put a logical OR between them. for value, 1.1.1.1&&2.2.2.2 would find attributes with the value being either of the two.
// ! - you can negate a search term. For example: google.com&&!mail would search for all attributes with value google.com but not ones that include mail. www.google.com would get returned, mail.google.com wouldn't.
public function restSearch($key='download', $value=false, $type=false, $category=false, $org=false, $tags=false, $from=false, $to=false, $last=false, $eventid=false, $withAttachments=false, $uuid=false, $publish_timestamp=false) {
public function restSearch($key = 'download', $value = false, $type = false, $category = false, $org = false, $tags = false, $from = false, $to = false, $last = false, $eventid = false, $withAttachments = false, $uuid = false, $publish_timestamp = false, $published = false) {
if ($tags) $tags = str_replace(';', ':', $tags);
$simpleFalse = array('value' , 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp');
foreach ($simpleFalse as $sF) {

View File

@ -142,6 +142,23 @@ class ACLComponent extends Component {
'previewIndex' => array(),
'view' => array(),
),
'galaxies' => array(
'attachClusterToEvent' => array('perm_tagger'),
'index' => array('*'),
'selectGalaxy' => array('perm_tagger'),
'selectCluster' => array('perm_tagger'),
'update' => array(),
'view' => array('*')
),
'galaxyClusters' => array(
'attachToEvent' => array('perm_tagger'),
'detachFromEvent' => array('perm_tagger'),
'index' => array(),
'view' => array()
),
'galaxyElements' => array(
'index' => array('*')
),
'jobs' => array(
'cache' => array('*'),
'getGenerateCorrelationProgress' => array('*'),

View File

@ -528,6 +528,7 @@ class EventsController extends AppController {
'ThreatLevel.name'))
),
));
$this->loadModel('GalaxyCluster');
// for REST, don't use the pagination. With this, we'll escape the limit of events shown on the index.
if ($this->_isRest()) {
$rules = array();
@ -560,6 +561,7 @@ class EventsController extends AppController {
}
$events[$k]['EventTag'] = array_values($events[$k]['EventTag']);
}
$events = $this->GalaxyCluster->attachClustersToEventIndex($events);
$this->set('events', $events);
} else {
$events = $this->paginate();
@ -569,6 +571,7 @@ class EventsController extends AppController {
if (Configure::read('MISP.showCorrelationsOnIndex')) $events = $this->Event->attachCorrelationCountToEvents($this->Auth->user(), $events);
if (Configure::read('MISP.showSightingsCountOnIndex') && Configure::read('MISP.Plugin.Sightings_enable') !== false) $events = $this->Event->attachSightingsCountToEvents($this->Auth->user(), $events);
if (Configure::read('MISP.showProposalsCountOnIndex')) $events = $this->Event->attachProposalsCountToEvents($this->Auth->user(), $events);
$events = $this->GalaxyCluster->attachClustersToEventIndex($events, true);
$this->set('events', $events);
}
@ -812,6 +815,13 @@ class EventsController extends AppController {
$this->set($alias, $currentModel->{$variable});
}
}
$this->loadModel('GalaxyCluster');
$cluster_names = $this->GalaxyCluster->find('list', array('fields' => array('GalaxyCluster.tag_name'), 'group' => array('GalaxyCluster.tag_name')));
foreach ($event['EventTag'] as $k => $eventTag) {
if (in_array($eventTag['Tag']['name'], $cluster_names)) {
unset($event['EventTag'][$k]);
}
}
$params = $this->Event->rearrangeEventForView($event);
$this->params->params['paging'] = array($this->modelClass => $params);
$this->set('event', $event);
@ -2425,7 +2435,7 @@ class EventsController extends AppController {
// the last 4 fields accept the following operators:
// && - you can use && between two search values to put a logical OR between them. for value, 1.1.1.1&&2.2.2.2 would find attributes with the value being either of the two.
// ! - you can negate a search term. For example: google.com&&!mail would search for all attributes with value google.com but not ones that include mail. www.google.com would get returned, mail.google.com wouldn't.
public function restSearch($key = 'download', $value = false, $type = false, $category = false, $org = false, $tags = false, $searchall = false, $from = false, $to = false, $last = false, $eventid = false, $withAttachments = false, $metadata = false, $uuid = false, $publish_timestamp = false, $timestamp = false) {
public function restSearch($key = 'download', $value = false, $type = false, $category = false, $org = false, $tags = false, $searchall = false, $from = false, $to = false, $last = false, $eventid = false, $withAttachments = false, $metadata = false, $uuid = false, $publish_timestamp = false, $timestamp = false, $published = false) {
if ($key != 'download') {
if (!$this->checkAuthUser($key)) {
throw new UnauthorizedException('This authentication key is not authorized to be used for exports. Contact your administrator.');
@ -2905,7 +2915,7 @@ class EventsController extends AppController {
}
}
public function removeTag($id = false, $tag_id = false) {
public function removeTag($id = false, $tag_id = false, $galaxy = false) {
if (!$this->request->is('post')) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that. Only POST requests are accepted.')), 'status'=>200));
}
@ -2920,10 +2930,10 @@ class EventsController extends AppController {
$this->request->data = $RearrangeTool->rearrangeArray($this->request->data, $rearrangeRules);
if ($id === false) $id = $this->request->data['event'];
if ($tag_id === false) $tag_id = $this->request->data['tag'];
if (empty($tag_id)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')),'status'=>200));
if (empty($tag_id)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid ' . ($galaxy ? 'Galaxy' : 'Tag') . '.')),'status'=>200));
if (!is_numeric($tag_id)) {
$tag = $this->Event->EventTag->Tag->find('first', array('recursive' => -1, 'conditions' => array('LOWER(Tag.name) LIKE' => strtolower(trim($tag_id)))));
if (empty($tag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status'=>200));
if (empty($tag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid ' . ($galaxy ? 'Galaxy' : 'Tag') . '.')), 'status'=>200));
$tag_id = $tag['Tag']['id'];
}
if (!is_numeric($id)) $id = $this->request->data['Event']['id'];
@ -2941,7 +2951,7 @@ class EventsController extends AppController {
'recursive' => -1,
));
$this->autoRender = false;
if (empty($eventTag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid event - tag combination.')),'status'=>200));
if (empty($eventTag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid event - ' . ($galaxy ? 'galaxy' : 'tag') . ' combination.')),'status'=>200));
$tag = $this->Event->EventTag->Tag->find('first', array(
'conditions' => array('Tag.id' => $tag_id),
'recursive' => -1,
@ -2950,9 +2960,9 @@ class EventsController extends AppController {
if ($this->Event->EventTag->delete($eventTag['EventTag']['id'])) {
$log = ClassRegistry::init('Log');
$log->createLogEntry($this->Auth->user(), 'tag', 'Event', $id, 'Removed tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" from event (' . $id . ')', 'Event (' . $id . ') untagged of Tag (' . $tag_id . ')');
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'Tag removed.')), 'status'=>200));
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => ($galaxy ? 'Galaxy' : 'Tag') . ' removed.')), 'status'=>200));
} else {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Tag could not be removed.')),'status'=>200));
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => ($galaxy ? 'Galaxy' : 'Tag') . ' could not be removed.')),'status'=>200));
}
}

View File

@ -0,0 +1,124 @@
<?php
App::uses('AppController', 'Controller');
class GalaxiesController extends AppController {
public $components = array('Session', 'RequestHandler');
public $paginate = array(
'limit' => 60,
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
'contain' => array(
),
'order' => array(
'Galaxy.id' => 'DESC'
),
);
public function index() {
$galaxies = $this->paginate();
$this->set('list', $galaxies);
}
public function update() {
if (!$this->request->is('post')) throw new MethodNotAllowedException('This action is only accessible via POST requests.');
$result = $this->Galaxy->update();
$this->redirect(array('controller' => 'galaxies', 'action' => 'index'));
}
public function view($id) {
if (!is_numeric($id)) throw new NotFoundException('Invalid galaxy.');
if ($this->_isRest()) {
$galaxy = $this->Galaxy->find('first', array(
'contain' => array('GalaxyCluster' => array('GalaxyElement'/*, 'GalaxyReference'*/)),
'recursive' => -1,
'conditions' => array('Galaxy.id' => $id)
));
if (empty($galaxy)) {
throw new NotFoundException('Galaxy not found.');
}
$this->set('Galaxy', $galaxy);
$this->set('_serialize', array('Galaxy'));
} else {
$galaxy = $this->Galaxy->find('first', array(
'recursive' => -1,
'conditions' => array('Galaxy.id' => $id)
));
if (empty($galaxy)) {
throw new NotFoundException('Galaxy not found.');
}
$this->set('galaxy', $galaxy);
}
}
public function selectGalaxy($event_id) {
$galaxies = $this->Galaxy->find('all', array('recursive' => -1));
$this->set('galaxies', $galaxies);
$this->set('event_id', $event_id);
$this->render('ajax/galaxy_choice');
}
public function selectCluster($event_id) {
$selectGalaxy = isset($this->request->data['Galaxy']['id']) ? $this->request->data['Galaxy']['id'] : false;
$conditions = array();
if ($selectGalaxy) {
$conditions = array('GalaxyCluster.galaxy_id' => $selectGalaxy);
}
$data = $this->Galaxy->GalaxyCluster->find('all', array(
'conditions' => $conditions,
'fields' => array('value', 'description', 'source'),
'contain' => array('GalaxyElement' => array('conditions' => array('GalaxyElement.key' => 'synonyms'))),
'recursive' => -1
));
$clusters = array();
$lookup_table = array();
foreach ($data as $k => $cluster) {
$cluster['GalaxyCluster']['synonyms_string'] = array();
foreach ($cluster['GalaxyElement'] as $element) {
$cluster['GalaxyCluster']['synonyms_string'][] = $element['value'];
if (isset($lookup_table[$element['value']])) {
$lookup_table[$element['value']][] = $cluster['GalaxyCluster']['id'];
} else {
$lookup_table[$element['value']] = array($cluster['GalaxyCluster']['id']);
}
}
$cluster['GalaxyCluster']['synonyms_string'] = implode(', ', $cluster['GalaxyCluster']['synonyms_string']);
unset($cluster['GalaxyElement']);
$clusters[$cluster['GalaxyCluster']['value']] = $cluster['GalaxyCluster'];
ksort($clusters);
if (isset($lookup_table[$cluster['GalaxyCluster']['value']])) {
$lookup_table[$cluster['GalaxyCluster']['value']][] = $cluster['GalaxyCluster']['id'];
} else {
$lookup_table[$cluster['GalaxyCluster']['value']] = array($cluster['GalaxyCluster']['id']);
}
}
$this->set('clusters', $clusters);
$this->set('event_id', $event_id);
$this->set('lookup_table', $lookup_table);
$this->render('ajax/cluster_choice');
}
public function attachClusterToEvent($event_id) {
$cluster_id = $this->request->data['Galaxy']['target_id'];
$cluster = $this->Galaxy->GalaxyCluster->find('first', array('recursive' => -1, 'conditions' => array('id' => $cluster_id), 'fields' => array('tag_name')));
$this->loadModel('Tag');
$tag_id = $this->Tag->captureTag(array('name' => $cluster['GalaxyCluster']['tag_name'], 'colour' => '#0088cc'), $this->Auth->user());
if ($tag_id === false) {
throw new MethodNotAllowedException('Could not attach cluster.');
}
$this->Tag->EventTag->create();
$existingTag = $this->Tag->EventTag->find('first', array('conditions' => array('event_id' => $event_id, 'tag_id' => $tag_id)));
if (!empty($existingTag)) {
$this->Session->setFlash('Cluster already attached.');
$this->redirect($this->referer());
}
$result = $this->Tag->EventTag->save(array('event_id' => $event_id, 'tag_id' => $tag_id));
if ($result) {
$this->Session->setFlash('Cluster attached');
$this->redirect($this->referer());
} else {
$this->Session->setFlash('Cluster could not be attached');
$this->redirect($this->referer());
}
}
}

View File

@ -0,0 +1,127 @@
<?php
App::uses('AppController', 'Controller');
class GalaxyClustersController extends AppController {
public $components = array('Session', 'RequestHandler');
public $paginate = array(
'limit' => 60,
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
'recursive' => -1,
'order' => array(
'GalaxyCluster.value' => 'ASC'
),
'contain' => array(
'GalaxyElement' => array(
'conditions' => array('GalaxyElement.key' => 'synonyms'),
'fields' => array('value')
)
)
);
public function index($id) {
$this->paginate['conditions'] = array('GalaxyCluster.galaxy_id' => $id);
$clusters = $this->paginate();
if (!empty($clusters)) {
$galaxyType = $clusters[0]['GalaxyCluster']['type'];
$tagPattern = 'misp-galaxy:' . $galaxyType . '="%s"';
$tags = $this->GalaxyCluster->getTags($galaxyType, false, $this->Auth->user());
foreach ($clusters as $k => $v) {
$clusters[$k]['GalaxyCluster']['synonyms'] = array();
foreach ($v['GalaxyElement'] as $element) {
$clusters[$k]['GalaxyCluster']['synonyms'][] = $element['value'];
}
if (isset($tags[sprintf($tagPattern, $v['GalaxyCluster']['value'])])) {
$clusters[$k]['GalaxyCluster']['tags'] = $tags[sprintf($tagPattern, $v['GalaxyCluster']['value'])];
} else {
$clusters[$k]['GalaxyCluster']['tags'] = 0;
}
}
}
$this->set('list', $clusters);
if ($this->request->is('ajax')) {
$this->layout = 'ajax';
$this->render('ajax/index');
}
}
public function view($id) {
$cluster = $this->GalaxyCluster->find('first', array(
'recursive' => -1,
'contain' => array('Galaxy'),
'conditions' => array('GalaxyCluster.id' => $id)
));
if (!empty($cluster)) {
$galaxyType = $cluster['GalaxyCluster']['type'];
$this->loadModel('Tag');
$tag = $this->Tag->find('first', array(
'conditions' => array(
'name' => $cluster['GalaxyCluster']['tag_name']
),
'fields' => array('id'),
'recursive' => -1,
'contain' => array('EventTag.tag_id')
));
if (!empty($tag)) {
$cluster['GalaxyCluster']['tag_count'] = count($tag['EventTag']);
$cluster['GalaxyCluster']['tag_id'] = $tag['Tag']['id'];
}
}
$this->set('cluster', $cluster);
}
public function attachToEvent($event_id, $tag_name) {
$this->loadModel('Event');
$this->Event->id = $event_id;
$this->Event->recursive = -1;
$event = $this->Event->read(array('id', 'org_id', 'orgc_id', 'distribution', 'sharing_group_id'), $event_id);
if (empty($event)) {
throw new MethodNotAllowedException('Invalid Event.');
}
if (!$this->_isSiteAdmin() && !$this->userRole['perm_sync']) {
if (!$this->userRole['perm_tagger'] || ($this->Auth->user('org_id') !== $event['Event']['org_id'] && $this->Auth->user('org_id') !== $event['Event']['orgc_id'])) {
throw new MethodNotAllowedException('Invalid Event.');
}
}
$tag = $this->Event->EventTag->Tag->find('first', array('conditions' => array('Tag.name' => $tag_name), 'recursive' => -1));
if (empty($tag)) {
$this->Event->EventTag->Tag->create();
$this->Event->EventTag->Tag->save(array('name' => $tag_name, 'colour' => '#0088cc', 'exportable' => 1));
$tag_id = $this->Event->EventTag->Tag->id;
} else {
$tag_id = $tag['Tag']['id'];
}
$existingEventTag = $this->Event->EventTag->find('first', array('conditions' => array('EventTag.tag_id' => $tag_id, 'EventTag.event_id' => $event_id), 'recursive' => -1));
if (empty($existingEventTag)) {
$this->Event->EventTag->create();
$this->Event->EventTag->save(array('EventTag.tag_id' => $tag_id, 'EventTag.event_id' => $event_id));
$this->Session->setFlash('Galaxy attached.');
} else {
$this->Session->setFlash('Galaxy already attached.');
}
$this->redirect($this->referer());
}
public function detachFromEvent($event_id, $tag_id) {
$this->loadModel('Event');
$this->Event->id = $event_id;
$this->Event->recursive = -1;
$event = $this->Event->read(array('id', 'org_id', 'orgc_id', 'distribution', 'sharing_group_id'), $event_id);
if (empty($event)) {
throw new MethodNotAllowedException('Invalid Event.');
}
if (!$this->_isSiteAdmin() && !$this->userRole['perm_sync']) {
if (!$this->userRole['perm_tagger'] || ($this->Auth->user('org_id') !== $event['Event']['org_id'] && $this->Auth->user('org_id') !== $event['Event']['orgc_id'])) {
throw new MethodNotAllowedException('Invalid Event.');
}
}
$existingEventTag = $this->Event->EventTag->find('first', array('conditions' => array('EventTag.tag_id' => $tag_id, 'EventTag.event_id' => $event_id), 'recursive' => -1));
if (empty($existingEventTag)) {
$this->Session->setFlash('Galaxy not attached.');
} else {
$this->Event->EventTag->delete($existingEventTag['EventTag']['id']);
$this->Session->setFlash('Galaxy successfully detached.');
}
$this->redirect($this->referer());
}
}

View File

@ -0,0 +1,25 @@
<?php
App::uses('AppController', 'Controller');
class GalaxyElementsController extends AppController {
public $components = array('Session', 'RequestHandler');
public $paginate = array(
'limit' => 20,
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
'recursive' => -1,
'order' => array(
'GalaxyElement.key' => 'ASC'
)
);
public function index($id) {
$this->paginate['conditions'] = array('GalaxyElement.galaxy_cluster_id' => $id);
$clusters = $this->paginate();
$this->set('list', $clusters);
if ($this->request->is('ajax')) {
$this->layout = 'ajax';
$this->render('ajax/index');
}
}
}

View File

@ -143,7 +143,7 @@ class TagsController extends AppController {
}
$this->redirect($this->referer());
}
public function edit($id) {
if (!$this->_isSiteAdmin() && !$this->userRole['perm_tag_editor']) {
throw new NotFoundException('You don\'t have permission to do that.');
@ -249,11 +249,17 @@ class TagsController extends AppController {
}
public function showEventTag($id) {
$this->helpers[] = 'TextColour';
$this->loadModel('EventTag');
if (!$this->EventTag->Event->checkIfAuthorised($this->Auth->user(), $id)) {
throw new MethodNotAllowedException('Invalid event.');
}
$this->loadModel('GalaxyCluster');
$cluster_names = $this->GalaxyCluster->find('list', array('fields' => array('GalaxyCluster.tag_name'), 'group' => array('GalaxyCluster.tag_name')));
$this->helpers[] = 'TextColour';
$tags = $this->EventTag->find('all', array(
'conditions' => array(
'event_id' => $id
'event_id' => $id,
'Tag.name !=' => $cluster_names
),
'contain' => array('Tag'),
'fields' => array('Tag.id', 'Tag.colour', 'Tag.name'),
@ -346,6 +352,11 @@ class TagsController extends AppController {
unset($expanded[$banned_tag]);
}
}
foreach ($options as $k => $v) {
if (substr($v, 0, strlen('misp-galaxy:')) === 'misp-galaxy:') {
unset($options[$k]);
}
}
$this->set('event_id', $event_id);
$this->set('options', $options);
$this->set('expanded', $expanded);

View File

@ -1167,6 +1167,8 @@ class UsersController extends AppController {
'fields' => array('Taxonomy.namespace')
));
$flatData = array();
$tagIds = $this->EventTag->Tag->find('list', array('fields' => array('Tag.name', 'Tag.id')));
$this->set('tagIds', $tagIds);
foreach ($tags as $key => $value) {
$name = explode(':', $value['name']);
$tags[$key]['taxonomy'] = 'custom';

View File

@ -1,7 +1,7 @@
<?php
class JSONConverterTool {
public function event2JSON($event, $isSiteAdmin=false) {
$toRearrange = array('Org', 'Orgc', 'SharingGroup', 'Attribute', 'ShadowAttribute', 'RelatedAttribute', 'RelatedEvent');
$toRearrange = array('Org', 'Orgc', 'SharingGroup', 'Attribute', 'ShadowAttribute', 'RelatedAttribute', 'RelatedEvent', 'Galaxy');
foreach ($toRearrange as $object) {
if (isset($event[$object])) {
$event['Event'][$object] = $event[$object];

View File

@ -36,7 +36,7 @@ class AppModel extends Model {
// major -> minor -> hotfix -> requires_logout
public $db_changes = array(
2 => array(
4 => array(18 => false, 19 => false, 20 => false, 25 => false, 27 => false, 32 => false, 33 => true, 38 => true, 39 => true, 40 => false, 42 => false, 44 => false, 45 => false, 49 => true, 50 => false, 51 => false, 52 => false, 55 => true)
4 => array(18 => false, 19 => false, 20 => false, 25 => false, 27 => false, 32 => false, 33 => true, 38 => true, 39 => true, 40 => false, 42 => false, 44 => false, 45 => false, 49 => true, 50 => false, 51 => false, 52 => false, 55 => true, 56 => true)
)
);
@ -444,6 +444,70 @@ class AppModel extends Model {
$sqlArray[] = 'ALTER TABLE feeds ADD publish tinyint(1) NOT NULL DEFAULT 0;';
$sqlArray[] = 'ALTER TABLE feeds ADD override_ids tinyint(1) NOT NULL DEFAULT 0;';
$sqlArray[] = "ALTER TABLE feeds ADD settings text NOT NULL DEFAULT '';";
break;
case '2.4.56':
$sqlArray[] =
"CREATE TABLE IF NOT EXISTS galaxies (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uuid` varchar(255) COLLATE utf8_bin NOT NULL,
`name` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT '',
`type` varchar(255) COLLATE utf8_bin NOT NULL,
`description` text COLLATE utf8_bin NOT NULL,
`version` varchar(255) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;";
$this->__addIndex('galaxies', 'name');
$this->__addIndex('galaxies', 'uuid');
$this->__addIndex('galaxies', 'type');
$sqlArray[] =
"CREATE TABLE IF NOT EXISTS galaxy_clusters (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uuid` varchar(255) COLLATE utf8_bin NOT NULL,
`type` varchar(255) COLLATE utf8_bin NOT NULL,
`value` text COLLATE utf8_bin NOT NULL,
`tag_name` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT '',
`description` text COLLATE utf8_bin NOT NULL,
`galaxy_id` int(11) NOT NULL,
`source` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT '',
`authors` text COLLATE utf8_bin NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;";
$this->__addIndex('galaxy_clusters', 'value', 255);
$this->__addIndex('galaxy_clusters', 'tag_name');
$this->__addIndex('galaxy_clusters', 'uuid');
$this->__addIndex('galaxy_clusters', 'type');
$sqlArray[] =
"CREATE TABLE IF NOT EXISTS galaxy_elements (
`id` int(11) NOT NULL AUTO_INCREMENT,
`galaxy_cluster_id` int(11) NOT NULL,
`key` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT '',
`value` text COLLATE utf8_bin NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;";
$this->__addIndex('galaxy_elements', 'key');
$this->__addIndex('galaxy_elements', 'value', 255);
$sqlArray[] =
"CREATE TABLE IF NOT EXISTS galaxy_reference (
`id` int(11) NOT NULL AUTO_INCREMENT,
`galaxy_cluster_id` int(11) NOT NULL,
`referenced_galaxy_cluster_id` int(11) NOT NULL,
`referenced_galaxy_cluster_uuid` varchar(255) COLLATE utf8_bin NOT NULL,
`referenced_galaxy_cluster_type` text COLLATE utf8_bin NOT NULL,
`referenced_galaxy_cluster_value` text COLLATE utf8_bin NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;";
$this->__addIndex('galaxy_reference', 'galaxy_cluster_id');
$this->__addIndex('galaxy_reference', 'referenced_galaxy_cluster_id');
$this->__addIndex('galaxy_reference', 'referenced_galaxy_cluster_value', 255);
$this->__addIndex('galaxy_reference', 'referenced_galaxy_cluster_type', 255);
break;
case 'fixNonEmptySharingGroupID':
$sqlArray[] = 'UPDATE `events` SET `sharing_group_id` = 0 WHERE `distribution` != 4;';
@ -535,6 +599,38 @@ class AppModel extends Model {
));
}
}
private function __addIndex($table, $field, $length = false) {
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
$dataSource = $dataSourceConfig['datasource'];
$this->Log = ClassRegistry::init('Log');
if ($dataSource == 'Database/Postgres') {
$addIndex = "CREATE INDEX idx_" . $table . "_" . $field . " ON " . $table . " (" . $field . ");";
} else {
if (isset($length)) {
$addIndex = "ALTER TABLE `" . $table . "` ADD INDEX `" . $field . "` (`" . $field . "`);";
} else {
$addIndex = "ALTER TABLE `" . $table . "` ADD INDEX `" . $field . "` (`" . $field . "`(" . $length . "));";
}
}
$result = true;
try {
$this->query($addIndex);
} catch (Exception $e) {
$result = false;
}
$this->Log->create();
$this->Log->save(array(
'org' => 'SYSTEM',
'model' => 'Server',
'model_id' => 0,
'email' => 'SYSTEM',
'action' => 'update_database',
'user_id' => 0,
'title' => ($result ? 'Added index ' : 'Failed to add index ') . $field . ' to ' . $table,
'change' => ($result ? 'Added index ' : 'Failed to add index ') . $field . ' to ' . $table,
));
}
public function cleanCacheFiles() {
Cache::clear();

View File

@ -1137,7 +1137,10 @@ class Event extends AppModel {
// includeAttachments: true will attach the attachments to the attributes in the data field
public function fetchEvent($user, $options = array()) {
if (isset($options['Event.id'])) $options['eventid'] = $options['Event.id'];
$possibleOptions = array('eventid', 'idList', 'tags', 'from', 'to', 'last', 'to_ids', 'includeAllTags', 'includeAttachments', 'event_uuid', 'distribution', 'sharing_group_id', 'disableSiteAdmin', 'metadata');
$possibleOptions = array('eventid', 'idList', 'tags', 'from', 'to', 'last', 'to_ids', 'includeAllTags', 'includeAttachments', 'event_uuid', 'distribution', 'sharing_group_id', 'disableSiteAdmin', 'metadata', 'includeGalaxy');
if (!isset($options['excludeGalaxy']) || !$options['excludeGalaxy']) {
$this->GalaxyCluster = ClassRegistry::init('GalaxyCluster');
}
foreach ($possibleOptions as &$opt) if (!isset($options[$opt])) $options[$opt] = false;
if ($options['eventid']) {
$conditions['AND'][] = array("Event.id" => $options['eventid']);
@ -1291,10 +1294,8 @@ class Event extends AppModel {
),
'SharingGroup' => $fieldsSharingGroup[(($user['Role']['perm_site_admin'] || $user['Role']['perm_sync']) ? 1 : 0)],
'EventTag' => array(
'Tag' => array(
'conditions' => $tagConditions
),
),
'Tag' => array('conditions' => $tagConditions)
)
)
);
if ($options['metadata']) {
@ -1321,10 +1322,34 @@ class Event extends AppModel {
}
}
if ($event['SharingGroup']['id'] == null) unset($event['SharingGroup']);
$event['Galaxy'] = array();
// unset empty event tags that got added because the tag wasn't exportable
if (!empty($event['EventTag'])) {
foreach ($event['EventTag'] as $k => &$eventTag) {
if (empty($eventTag['Tag'])) unset($event['EventTag'][$k]);
if (empty($eventTag['Tag'])) {
unset($event['EventTag'][$k]);
continue;
}
if (!isset($options['excludeGalaxy']) || !$options['excludeGalaxy']) {
if (substr($eventTag['Tag']['name'], 0, strlen('misp-galaxy:')) === 'misp-galaxy:') {
$cluster = $this->GalaxyCluster->getCluster($eventTag['Tag']['name']);
if ($cluster) {
$found = false;
foreach ($event['Galaxy'] as $k => $galaxy) {
if ($galaxy['id'] == $cluster['GalaxyCluster']['Galaxy']['id']) {
$found = true;
unset($cluster['GalaxyCluster']['Galaxy']);
$event['Galaxy'][$k]['GalaxyCluster'][] = $cluster['GalaxyCluster'];
}
}
if (!$found) {
$event['Galaxy'][] = $cluster['GalaxyCluster']['Galaxy'];
unset($cluster['GalaxyCluster']['Galaxy']);
$event['Galaxy'][count($event['Galaxy']) - 1]['GalaxyCluster'][] = $cluster['GalaxyCluster'];
}
}
}
}
}
$event['EventTag'] = array_values($event['EventTag']);
}
@ -2691,7 +2716,7 @@ class Event extends AppModel {
return true;
}
// convenience method to check whther a user can see an event
// convenience method to check whether a user can see an event
public function checkIfAuthorised($user, $id) {
if (!isset($user['id'])) throw new MethodNotAllowedException('Invalid user.');
$this->id = $id;

104
app/Model/Galaxy.php Normal file
View File

@ -0,0 +1,104 @@
<?php
App::uses('AppModel', 'Model');
class Galaxy extends AppModel{
public $useTable = 'galaxies';
public $recursive = -1;
public $actsAs = array(
'Containable',
);
public $validate = array(
);
public $hasMany = array(
'GalaxyCluster' => array('dependent' => true)
);
public function beforeValidate($options = array()) {
parent::beforeValidate();
return true;
}
public function beforeDelete($cascade = true) {
$this->GalaxyCluster->deleteAll(array('GalaxyCluster.galaxy_id' => $this->id));
}
private function __load_galaxies() {
$dir = new Folder(APP . 'files' . DS . 'misp-galaxy' . DS . 'galaxies');
$files = $dir->find('.*\.json');
$galaxies = array();
foreach ($files as $file) {
$file = new File($dir->pwd() . DS . $file);
$galaxies[] = json_decode($file->read(), true);
$file->close();
}
foreach ($galaxies as $galaxy) {
$this->deleteAll(array('Galaxy.type' => $galaxy['type']));
}
$this->saveMany($galaxies);
return $this->find('list', array('recursive' => -1, 'fields' => array('type', 'id')));
}
public function update() {
$galaxies = $this->__load_galaxies();
$dir = new Folder(APP . 'files' . DS . 'misp-galaxy' . DS . 'clusters');
$files = $dir->find('.*\.json');
$cluster_packages = array();
foreach ($files as $file) {
$file = new File($dir->pwd() . DS . $file);
$cluster_packages[] = json_decode($file->read(), true);
$file->close();
}
foreach ($cluster_packages as $cluster_package) {
if (!isset($galaxies[$cluster_package['type']])) {
continue;
}
$template = array(
'source' => isset($cluster_package['source']) ? $cluster_package['source'] : '',
'authors' => json_encode(isset($cluster_package['authors']) ? $cluster_package['authors'] : array(), true),
'uuid' => isset($cluster_package['uuid']) ? $cluster_package['uuid'] : '',
'galaxy_id' => $galaxies[$cluster_package['type']],
'type' => $cluster_package['type'],
'tag_name' => 'misp-galaxy:' . $cluster_package['type'] . '="'
);
foreach ($cluster_package['values'] as $cluster) {
$this->GalaxyCluster->create();
$cluster_to_save = $template;
if (isset($cluster['description'])) {
$cluster_to_save['description'] = $cluster['description'];
unset($cluster['description']);
}
$cluster_to_save['value'] = $cluster['value'];
$cluster_to_save['tag_name'] = $cluster_to_save['tag_name'] . $cluster['value'] . '"';
unset($cluster['value']);
$this->GalaxyCluster->save($cluster_to_save);
$galaxyClusterId = $this->GalaxyCluster->id;
$elements = array();
if (isset($cluster['meta'])) {
foreach ($cluster['meta'] as $key => $value) {
if (is_array($value)) {
foreach ($value as $v) {
$elements[] = array(
'galaxy_cluster_id' => $galaxyClusterId,
'key' => $key,
'value' => $v
);
}
} else {
$elements[] = array(
'galaxy_cluster_id' => $this->GalaxyCluster->id,
'key' => $key,
'value' => $value
);
}
}
}
$this->GalaxyCluster->GalaxyElement->saveMany($elements);
}
}
return true;
}
}

179
app/Model/GalaxyCluster.php Normal file
View File

@ -0,0 +1,179 @@
<?php
App::uses('AppModel', 'Model');
class GalaxyCluster extends AppModel{
public $useTable = 'galaxy_clusters';
public $recursive = -1;
public $actsAs = array(
'Containable',
);
public $validate = array(
);
public $belongsTo = array(
'Galaxy' => array(
'className' => 'Galaxy',
'foreignKey' => 'galaxy_id',
),
'Tag' => array(
'className' => 'Tag',
'foreignKey' => false,
'Tag.name = GalaxyCluster.tag_name'
)
);
public $hasMany = array(
'GalaxyElement' => array('dependent' => true),
// 'GalaxyReference'
);
public function beforeValidate($options = array()) {
parent::beforeValidate();
return true;
}
public function beforeDelete($cascade = true) {
$this->GalaxyElement->deleteAll(array('GalaxyElement.galaxy_cluster_id' => $this->id));
}
// receive a full galaxy and add all new clusters, update existing ones contained in the new galaxy, cull old clusters that are removed from the galaxy
public function update($id, $galaxy) {
$existingClusters = $this->find('all', array(
'conditions' => array('GalaxyCluster.galaxy_id' => $id),
'recursive' => -1,
));
foreach ($galaxy['values'] as $cluster) {
$oldCluster = false;
if (!empty($existingClusters)) {
foreach ($existingClusters as $k => $existingCluster) {
if ($existingCluster['GalaxyCluster']['value'] == $cluster['value']) {
$oldCluster = true;
if ($cluster['description'] != $existingCluster['GalaxyCluster']['description']) {
$existingCluster['GalaxyCluster']['description'] = $cluster['description'];
$this->GalaxyElement->deleteAll('galaxy_cluster_id' == $existingCluster['GalaxyCluster']['id']);
$this->save($existingCluster);
$template = array('galaxy_cluster_id' => $this->id);
$toSave = array();
foreach ($cluster as $key => $value) {
if (in_array($key, array('value', 'description'))) {
continue;
}
$tosave[] = array_merge($template, array('key' => $key, 'value' => $value));
}
$this->GalaxyElement->saveMany($toSave);
}
unset($existingClusters[$k]);
}
}
}
if (!$oldCluster) {
$newCluster = array_intersect_key($cluster, array_flip(array('value', 'description')));
$newCluster['galaxy_id'] = $id;
$newCluster['type'] = $galaxy['type'];
$toSave[] = $newCluster;
}
$final = array();
if (!empty($existingCluster)) {
$fieldsToUpdate = array('description', '');
$final = $existingCluster;
}
}
$this->saveMany($toSave);
// Let's retrieve the full list of clusters we have for the given galaxy and pass it to the element system
$existingClusters = $this->find('all', array(
'conditions' => array('GalaxyCluster.galaxy_id'),
'contain' => array('GalaxyElement'/*, 'GalaxyReference'*/)
));
$this->GalaxyElement->update($id, $existingClusters, $galaxy['values']);
}
/* Return a list of all tags associated with the cluster specific cluster within the galaxy (or all clusters if $clusterValue is false)
* The counts are restricted to the event IDs that the user is allowed to see.
*/
public function getTags($galaxyType, $clusterValue = false, $user) {
$this->Event = ClassRegistry::init('Event');
$event_ids = $this->Event->fetchEventIds($user, false, false, false, true);
$tags = $this->Event->EventTag->Tag->find('list', array(
'conditions' => array('name LIKE' => 'misp-galaxy:' . $galaxyType . '="' . ($clusterValue ? $clusterValue : '%') .'"'),
'fields' => array('name', 'id'),
));
$this->Event->EventTag->virtualFields['tag_count'] = 'COUNT(id)';
$tagCounts = $this->Event->EventTag->find('list', array(
'conditions' => array('EventTag.tag_id' => array_values($tags), 'EventTag.event_id' => $event_ids),
'fields' => array('EventTag.tag_id', 'EventTag.tag_count'),
'group' => array('EventTag.tag_id')
));
foreach ($tags as $k => $v) {
if (isset($tagCounts[$v])) {
$tags[$k] = array('count' => $tagCounts[$v], 'tag_id' => $v);
} else {
unset($tags[$k]);
}
}
return $tags;
}
/* Fetch a cluster along with all elements and the galaxy it belongs to
* - In the future, once we move to galaxy 2.0, pass a user along for access control
* - maybe in the future remove the galaxy itself once we have logos with each galaxy
*/
public function getCluster($name) {
$objects = array('Galaxy', 'GalaxyElement');
$cluster = $this->find('first', array(
'conditions' => array('GalaxyCluster.tag_name' => $name),
'contain' => array('Galaxy', 'GalaxyElement')
));
if (!empty($cluster)) {
$cluster['GalaxyCluster']['authors'] = json_decode($cluster['GalaxyCluster']['authors'], true);
if (isset($cluster['Galaxy'])) {
$cluster['GalaxyCluster']['Galaxy'] = $cluster['Galaxy'];
unset($cluster['Galaxy']);
}
$elements = array();
foreach ($cluster['GalaxyElement'] as $element) {
if (!isset($elements[$element['key']])) {
$elements[$element['key']] = array($element['value']);
} else {
$elements[$element['key']][] = $element['value'];
}
}
unset($cluster['GalaxyElement']);
$this->Tag = ClassRegistry::init('Tag');
$tag_id = $this->Tag->find('first', array(
'conditions' => array(
'Tag.name' => $cluster['GalaxyCluster']['tag_name']
),
'recursive' => -1,
'fields' => array('Tag.id')
)
);
if (!empty($tag_id)) {
$cluster['GalaxyCluster']['tag_id'] = $tag_id['Tag']['id'];
}
$cluster['GalaxyCluster']['meta'] = $elements;
}
return $cluster;
}
public function attachClustersToEventIndex($events, $replace = false) {
foreach ($events as $k => $event) {
foreach ($event['EventTag'] as $k2 => $eventTag) {
if (substr($eventTag['Tag']['name'], 0, strlen('misp-galaxy:')) === 'misp-galaxy:') {
$cluster = $this->getCluster($eventTag['Tag']['name']);
if ($cluster) {
$events[$k]['GalaxyCluster'][] = $cluster['GalaxyCluster'];
if ($replace) {
unset($events[$k]['EventTag'][$k2]);
}
}
}
}
}
return $events;
}
}

View File

@ -0,0 +1,60 @@
<?php
App::uses('AppModel', 'Model');
class GalaxyElement extends AppModel{
public $useTable = 'galaxy_elements';
public $recursive = -1;
public $actsAs = array(
'Containable',
);
public $validate = array(
);
public $belongsTo = array(
'GalaxyCluster' => array(
'className' => 'GalaxyCluster',
'foreignKey' => 'galaxy_cluster_id',
)
);
public function beforeValidate($options = array()) {
parent::beforeValidate();
return true;
}
public function update($galaxy_id, $oldClusters, $newClusters) {
debug($oldClusters);
debug($newClusters);
throw new Exception();
$elementsToSave = array();
// Since we are dealing with flat files as the end all be all content, we are safe to just drop all of the old clusters and recreate them.
foreach ($oldClusters as $oldCluster) {
$this->deleteAll(array('GalaxyElement.galaxy_cluster_id' => $oldCluster['GalaxyCluster']['id']));
}
foreach ($newClusters as $newCluster) {
$tempCluster = array();
foreach ($newCluster as $key => $value) {
// Don't store the reserved fields as elements
if ($key == 'description' || $key == 'value') {
continue;
}
if (is_array($value)) {
foreach ($value as $arrayElement) {
$tempCluster[] = array('key' => $key, 'value' => $arrayElement);
}
} else {
$tempCluster[] = array('key' => $key, 'value' => $value);
}
}
foreach ($tempCluster as $key => $value) {
$tempCluster[$key]['galaxy_cluster_id'] = $oldCluster['GalaxyCluster']['id'];
}
$elementsToSave = array_merge($elementsToSave, $tempCluster);
}
$this->saveMany($elementsToSave);
}
}

View File

@ -113,7 +113,7 @@ class Tag extends AppModel {
$tag = array(
'name' => $tag['name'],
'colour' => $tag['colour'],
'exportable' => $tag['exportable'],
'exportable' => isset($tag['exportable']) ? $tag['exportable'] : 0,
'org_id' => 0
);
$this->save($tag);
@ -151,7 +151,7 @@ class Tag extends AppModel {
return $colour;
}
public function quickAdd($name, $colour = false) {
public function quickAdd($name, $colour = false, $returnId = false) {
$this->create();
if ($colour === false) $colour = $this->random_color();
$data = array(

View File

@ -23,6 +23,7 @@
endif;
?>
<th><?php echo $this->Paginator->sort('id');?></th>
<th>Clusters</th>
<?php if (Configure::read('MISP.tagging')): ?>
<th class="filter">Tags</th>
<?php endif; ?>
@ -90,6 +91,36 @@
<td style="width:30px;">
<a href="<?php echo $baseurl."/events/view/".$event['Event']['id'] ?>"><?php echo $event['Event']['id'];?></a>
</td>
<td class="shortish">
<?php
$clusterList = array();
$galaxyList = array();
$galaxy_id = 0;
if (isset($event['GalaxyCluster'])):
foreach ($event['GalaxyCluster'] as $cluster):
$galaxy_id = $cluster['Galaxy']['id'];
if (!isset($galaxyList[$cluster['Galaxy']['id']])) {
$galaxyList[$cluster['Galaxy']['id']] = $cluster['Galaxy']['name'];
}
$clusterList[$cluster['Galaxy']['id']][] = array('value' => $cluster['value'], 'id' => $cluster['id']);
endforeach;
endif;
foreach ($clusterList as $galaxy_id => $clusters):
?>
<span class="blue bold"><a href="<?php echo $baseurl; ?>/galaxies/view/<?php echo h($galaxy_id); ?>"><?php echo h($galaxyList[$galaxy_id]); ?></a>:</span>
<?php
foreach ($clusters as $cluster):
?>
<br />
<span class="blue">
&nbsp;&nbsp;&nbsp;&nbsp;
<a href="<?php echo $baseurl; ?>/galaxy_clusters/view/<?php echo h($cluster['id']); ?>"><?php echo h($cluster['value']); ?></a>
</span>
<?php
endforeach;
endforeach;
?>&nbsp;
</td>
<?php if (Configure::read('MISP.tagging')): ?>
<td style = "max-width: 200px;width:10px;">
<?php foreach ($event['EventTag'] as $tag):

View File

@ -0,0 +1,86 @@
<?php
$fixed_fields = array('decription', 'source', 'authors');
foreach ($event['Galaxy'] as $galaxy):
?>
<div>
<span title="<?php echo isset($galaxy['description']) ? h($galaxy['description']) : h($galaxy['name']);?>" class="bold blue" style="font-size:14px;">
<?php echo h($galaxy['name']); ?>
</span>
<?php
foreach ($galaxy['GalaxyCluster'] as $cluster):
?>
<div style="margin-left:20px;">
<span class="bold blue expandable useCursorPointer"><?php echo h($cluster['value']); ?></span>&nbsp;
<?php
echo $this->Form->postLink('',
$baseurl . '/galaxy_clusters/detachFromEvent/' . $event['Event']['id'] . '/' . $cluster['tag_id'],
array('class' => 'icon-trash', 'title' => 'Delete'),
__('Are you sure you want to detach %s from this event?', h($cluster['value']))
);
?>
<div style="margin-left:40px;" class="hidden blue">
<table style="width:100%">
<?php
foreach ($fixed_fields as $fixed_field):
if (isset($cluster[$fixed_field])):
?>
<tr>
<td style="width:25%;vertical-align: text-top; padding-bottom:10px;"><?php echo h(ucfirst($fixed_field)); ?></td>
<td style="width:75%; padding-bottom:10px;">
<?php
if (is_array($cluster[$fixed_field])) {
$cluster[$fixed_field] = implode("\n", $cluster[$fixed_field]);
echo nl2br(h($cluster[$fixed_field]));
} else {
echo h($cluster[$fixed_field]);
}
?>
</td>
</tr>
<?php
endif;
endforeach;
foreach ($cluster['meta'] as $key => $value):
?>
<tr>
<td style="width:25%;vertical-align: text-top; padding-bottom:10px;"><?php echo h(ucfirst($key)); ?></td>
<td style="width:75%; padding-bottom:10px;">
<?php
if ($key == 'refs'):
foreach ($value as $k => $v):
$value[$k] = '<a href="' . h($v) . '">' . h($v) . '</a>';
endforeach;
echo nl2br(implode("\n", $value));
else:
echo nl2br(h(implode("\n", $value)));
endif;
?>
</td>
</tr>
<?php
endforeach;
?>
</table>
<?php
?>
</div>
</div>
<?php
endforeach;
?>
</div>
<?php
endforeach;
?>
<script type="text/javascript">
$(document).ready(function () {
$('.expandable').click(function() {
$(this).parent().children('div').toggle();
});
$('.delete-cluster').click(function() {
var tagName = $(this).data('tag-name');
removeTag($id = false, $tag_id = false, $galaxy = false);
});
});
</script>

View File

@ -50,6 +50,17 @@
</ul>
</li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
Galaxies
<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="<?php echo $baseurl;?>/galaxies/index">List Galaxies</a></li>
</ul>
</li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
Input Filters
@ -88,6 +99,9 @@
<li><a href="<?php echo $baseurl;?>/pages/display/doc/quickstart">User Guide</a></li>
<li><a href="<?php echo $baseurl;?>/users/terms">Terms &amp; Conditions</a></li>
<li><a href="<?php echo $baseurl;?>/users/statistics">Statistics</a></li>
<li class="divider"></li>
<li><a href="<?php echo $baseurl;?>/threads/index">List Discussions</a></li>
<li><a href="<?php echo $baseurl;?>/posts/add">Start Discussion</a></li>
</ul>
</li>
@ -162,16 +176,6 @@
</ul>
</li>
<?php endif;?>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
Discussions
<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="<?php echo $baseurl;?>/threads/index">List Discussions</a></li>
<li><a href="<?php echo $baseurl;?>/posts/add">Start Discussion</a></li>
</ul>
</li>
</ul>
</div>
<div class="nav-collapse collapse pull-right">

View File

@ -0,0 +1,36 @@
<div style="width:100%;display:inline-block;">
<?php
foreach ($tags as $tag): ?>
<div style="overflow:hidden;white-space:nowrap;float:left;">
<div style="padding-right:0px;float: left;">
<?php if ($isSiteAdmin): ?>
<a href="<?php echo $baseurl;?>/events/index/searchtag:<?php echo h($tag['Tag']['id']); ?>" class="tagFirstHalf" style="background-color:<?php echo h($tag['Tag']['colour']);?>;color:<?php echo $this->TextColour->getTextColour($tag['Tag']['colour']);?>"><?php echo h($tag['Tag']['name']); ?></a>
<?php else: ?>
<a href="<?php echo $baseurl;?>/events/index/searchtag:<?php echo h($tag['Tag']['id']); ?>" class=tag style="background-color:<?php echo h($tag['Tag']['colour']);?>;color:<?php echo $this->TextColour->getTextColour($tag['Tag']['colour']);?>"><?php echo h($tag['Tag']['name']); ?></a>
<?php endif; ?>
</div>
<div style="padding-left:0px;padding-right:5px;float:left;">
<?php if ($isSiteAdmin): ?>
<?php
echo $this->Form->create('Server', array('id' => 'removeTag_' . h($tag['Tag']['id']), 'url' => '/servers/removeTag/' . h($server['Server']['id']) . '/' . h($tag['Tag']['id']), 'style' => 'margin:0px;'));
?>
<div class="tagSecondHalf useCursorPointer noPrint" onClick="removeServerTag('<?php echo h($server['Server']['id']); ?>', '<?php echo h($tag['Tag']['id']); ?>');">x</div>
<?php
echo $this->Form->end();
?>
<?php else: ?>
&nbsp;
<?php endif; ?>
</div>
</div>
<?php
endforeach;
?>
<div style="float:left">
<?php if ($isSiteAdmin): ?>
<button id="addTagButton" class="btn btn-inverse noPrint" style="line-height:10px; padding: 4px 4px;" onClick="getPopup('<?php echo h($server['Server']['id']); ?>', 'tags', 'selectTaxonomy');">+</button>
<?php else:?>
&nbsp;
<?php endif; ?>
</div>
</div>

View File

@ -321,13 +321,35 @@
case 'news': ?>
<li id='liindex'><a href="<?php echo $baseurl;?>/news/index">View News</a></li>
<?php
if ($isSiteAdmin): ?>
if ($isSiteAdmin):
?>
<li id='liadd'><a href="<?php echo $baseurl;?>/news/add">Add News Item</a></li>
<?php if ($menuItem === 'edit'): ?>
<li class="active"><a href="#">Edit News Item</a></li>
<?php endif;
endif;
break;
case 'galaxies':
?>
<li id='liindex'><a href="<?php echo $baseurl;?>/galaxies/index">List Galaxies</a></li>
<?php
if ($isSiteAdmin):
?>
<li><?php echo $this->Form->postLink('Update Galaxies', array('controller' => 'galaxies', 'action' => 'update'), null, __('Are you sure you want to reimport all galaxies from the submodule?')); ?></li>
<?php
endif;
if ($menuItem === 'view'):
?>
<li class="active"><a href="#">View Galaxy</a></li>
<?php
endif;
if ($menuItem === 'view_cluster'):
?>
<li class="active"><a href="#">View Cluster</a></li>
<?php
endif;
break;
}
?>
</ul>

View File

@ -0,0 +1,19 @@
<?php
echo $this->Form->create('Event', array('class' => 'inline-form inline-field-form', 'url' => '/events/quickEdit/' . $event['Event']['id'] . '/' . $field));
?>
<div class='inline-input inline-input-container'>
<div class="inline-input-accept inline-input-button inline-input-passive"><span class = "icon-ok"></span></div>
<div class="inline-input-decline inline-input-button inline-input-passive"><span class = "icon-remove"></span></div>
<?php
echo $this->Form->input('category', array(
'options' => array(array_combine($typeCategory[$object['type']], $typeCategory[$object['type']])),
'label' => false,
'selected' => $object['category'],
'error' => array('escape' => false),
'class' => 'inline-input',
'id' => 'Attribute_' . $object['id'] . '_category_field',
'div' => false
));
echo $this->Form->end();
?>
</div>

View File

@ -5,6 +5,9 @@ foreach ($events as $key => $event) {
unset($events[$key]['Event']);
$events[$key]['Org'] = $event['Org'];
$events[$key]['Orgc'] = $event['Orgc'];
if (isset($event['GalaxyCluster'])) {
$events[$key]['GalaxyCluster'] = $event['GalaxyCluster'];
}
if (isset($event['EventTag'])) $events[$key]['EventTag'] = $event['EventTag'];
$events[$key]['SharingGroup'] = $event['SharingGroup'];

View File

@ -108,14 +108,16 @@
?>
&nbsp;
</dd>
<?php if (isset($event['User']['email']) && ($isSiteAdmin || ($isAdmin && $me['org_id'] == $event['Event']['org_id']))): ?>
<dt>Email</dt>
<dd>
<?php echo h($event['User']['email']); ?>
&nbsp;
</dd>
<?php endif; ?>
<?php
<?php
if (isset($event['User']['email']) && ($isSiteAdmin || ($isAdmin && $me['org_id'] == $event['Event']['org_id']))):
?>
<dt>Email</dt>
<dd>
<?php echo h($event['User']['email']); ?>
&nbsp;
</dd>
<?php
endif;
if (Configure::read('MISP.tagging')): ?>
<dt>Tags</dt>
<dd class="eventTagContainer">
@ -223,30 +225,30 @@
</div>
<br />
<div class="toggleButtons">
<button class="btn btn-inverse toggle-left btn.active qet" id="pivots_active">
<button class="btn btn-inverse toggle-left btn.active qet galaxy-toggle-button" id="pivots_toggle" data-toggle-type="pivots">
<span class="icon-minus icon-white" style="vertical-align:top;"></span>Pivots
</button>
<button class="btn btn-inverse toggle-left qet" style="display:none;" id="pivots_inactive">
<span class="icon-plus icon-white" style="vertical-align:top;"></span>Pivots
<button class="btn btn-inverse toggle qet galaxy-toggle-button" id="galaxies_toggle" data-toggle-type="galaxies">
<span class="icon-minus icon-white" style="vertical-align:top;"></span>Galaxy
</button>
<button class="btn btn-inverse toggle qet" id="attributes_active">
<button class="btn btn-inverse toggle qet galaxy-toggle-button" id="attributes_toggle" data-toggle-type="attributes">
<span class="icon-minus icon-white" style="vertical-align:top;"></span>Attributes
</button>
<button class="btn btn-inverse toggle qet" id="attributes_inactive" style="display:none;">
<span class="icon-plus icon-white" style="vertical-align:top;"></span>Attributes
</button>
<button class="btn btn-inverse toggle-right qet" id="discussions_active">
<button class="btn btn-inverse toggle-right qet galaxy-toggle-button" id="discussions_toggle" data-toggle-type="discussions">
<span class="icon-minus icon-white" style="vertical-align:top;"></span>Discussion
</button>
<button class="btn btn-inverse toggle-right qet" id="discussions_inactive" style="display:none;">
<span class="icon-plus icon-white" style="vertical-align:top;"></span>Discussion
</button>
</div>
<br />
<br />
<div id="pivots_div">
<?php if (sizeOf($allPivots) > 1) echo $this->element('pivot'); ?>
</div>
<div id="galaxies_div" class="info_container" style="width:33%">
<h4 class="blue">Galaxies
<span class="useCursorPointer blue bold" id="addGalaxy" data-event-id="<?php echo h($event['Event']['id']); ?>">+</span>
</h4>
<?php echo $this->element('galaxyQuickView', array()); ?>
</div>
<div id="attributes_div">
<?php echo $this->element('eventattribute'); ?>
</div>
@ -256,50 +258,16 @@
</div>
</div>
<script type="text/javascript">
// tooltips
var showContext = false;
$(document).ready(function () {
popoverStartup();
//loadEventTags("<?php echo $event['Event']['id']; ?>");
$("th, td, dt, div, span, li").tooltip({
'placement': 'top',
'container' : 'body',
delay: { show: 500, hide: 100 }
});
$('#discussions_active').click(function() {
$('#discussions_div').hide();
$('#discussions_active').hide();
$('#discussions_inactive').show();
});
$('#discussions_inactive').click(function() {
$('#discussions_div').show();
$('#discussions_active').show();
$('#discussions_inactive').hide();
});
$('#attributes_active').click(function() {
$('#attributes_div').hide();
$('#attributes_active').hide();
$('#attributes_inactive').show();
});
$('#attributes_inactive').click(function() {
$('#attributes_div').show();
$('#attributes_active').show();
$('#attributes_inactive').hide();
});
$('#pivots_active').click(function() {
$('#pivots_div').hide();
$('#pivots_active').hide();
$('#pivots_inactive').show();
});
$('#pivots_inactive').click(function() {
$('#pivots_div').show();
$('#pivots_active').show();
$('#pivots_inactive').hide();
});
// $.get("/events/viewEventAttributes/<?php echo $event['Event']['id']; ?>", function(data) {
// $("#attributes_div").html(data);
// });
});
$.get("/threads/view/<?php echo $event['Event']['id']; ?>/true", function(data) {
$("#discussions_div").html(data);
});

View File

@ -0,0 +1,61 @@
<div class="popover_choice select_cluster">
<legend>Select Cluster</legend>
<div class="hidden">
<?php
echo $this->Form->create('Galaxy', array('url' => '/galaxies/attachClusterToEvent/' . $event_id, 'style' => 'margin:0px;'));
echo $this->Form->input('target_id', array('type' => 'text'));
echo $this->Form->end();
?>
</div>
<div style="text-align:right;width:100%;" class="select_tag_search">
<input id="clusterFilterField" style="width:100%;border:0px;padding:0px;" placeholder="search clusters..."/>
</div>
<div class="popover_choice_main" id ="popover_choice_main">
<table style="width:100%;">
<?php
foreach ($clusters as $k => $cluster):
$title = isset($cluster['description']) ? $cluster['description'] : $cluster['value'];
?>
<tr id="field_<?php echo h($cluster['id']); ?>" style="border-bottom:1px solid black;" class="templateChoiceButton filterableButton">
<td class="clusterSelectChoice" data-event-id="<?php echo h($event_id); ?>" data-cluster-id="<?php echo h($cluster['id']); ?>" style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" title="<?php echo 'Synonyms: ' . h($cluster['synonyms_string']); ?>"><?php echo h($cluster['value']); ?></td>
</tr>
<?php
endforeach;
?>
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
<td class="clusterSelectBack" style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" data-event-id="<?php echo h($event_id); ?>" title="Select Galaxy">Back to Galaxy Selection</td>
</tr>
</table>
</div>
<div class="templateChoiceButton templateChoiceButtonLast" onClick="cancelPopoverForm();">Cancel</div>
</div>
<script type="text/javascript">
var lookup_table = <?php echo json_encode($lookup_table); ?>;
$(document).ready(function() {
resizePopoverBody();
$("#clusterFilterField").focus();
});
$('.clusterSelectBack').click(function() {
getPopup($(this).data('event-id'), 'galaxies', 'selectGalaxy');
});
$('.clusterSelectChoice').click(function() {
quickSubmitGalaxyForm($(this).data('event-id'), $(this).data('cluster-id'));
});
$('#clusterFilterField').keyup(function() {
var filterString = $("#clusterFilterField").val().toLowerCase();
$('.filterableButton').hide();
$.each(lookup_table, function(index, value) {
var found = false;
if (index.toLowerCase().indexOf(filterString) != -1) {
$.each(value, function(k, v) {
$('#field_' + v).show();
});
}
});
});
$(window).resize(function() {
resizePopoverBody();
});
</script>

View File

@ -0,0 +1,25 @@
<div class="popover_choice select_galaxy_source">
<legend>Select Cluster Source</legend>
<div class="popover_choice_main" id ="popover_choice_main">
<table style="width:100%;">
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($event_id); ?>/0', 'galaxies', 'selectCluster');">All Galaxies</td>
</tr>
<?php foreach ($galaxies as $galaxy): ?>
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($event_id); ?>/<?php echo h($galaxy['Galaxy']['id']);?>', 'galaxies', 'selectCluster');">Galaxy: <?php echo h($galaxy['Galaxy']['name']); ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
<div class="templateChoiceButton templateChoiceButtonLast" onClick="cancelPopoverForm();">Cancel</div>
</div>
<script type="text/javascript">
$(document).ready(function() {
resizePopoverBody();
});
$(window).resize(function() {
resizePopoverBody();
});
</script>

View File

@ -0,0 +1,58 @@
<div class="regexp index">
<h2>Galaxies</h2>
<div class="pagination">
<ul>
<?php
$this->Paginator->options(array(
'update' => '.span12',
'evalScripts' => true,
'before' => '$(".progress").show()',
'complete' => '$(".progress").hide()',
));
echo $this->Paginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
echo $this->Paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
?>
</ul>
</div>
<table class="table table-striped table-hover table-condensed">
<tr>
<th><?php echo $this->Paginator->sort('id');?></th>
<th><?php echo $this->Paginator->sort('name');?></th>
<th><?php echo $this->Paginator->sort('version');?></th>
<th><?php echo $this->Paginator->sort('description');?></th>
<th class="actions"><?php echo $this->Paginator->sort('description');?></th>
</tr><?php
foreach ($list as $item):?>
<tr>
<td class="short"><?php echo h($item['Galaxy']['id']);?>&nbsp;</td>
<td><?php echo h($item['Galaxy']['name']);?>&nbsp;</td>
<td class="short"><?php echo h($item['Galaxy']['version']);?>&nbsp;</td>
<td><?php echo h($item['Galaxy']['description']);?>&nbsp;</td>
<td class="short action-links">
<?php echo $this->Html->link('', array('action' => 'view', $item['Galaxy']['id']), array('class' => 'icon-list-alt', 'title' => 'View'));?>
</td>
</tr><?php
endforeach;?>
</table>
<p>
<?php
echo $this->Paginator->counter(array(
'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')
));
?>
</p>
<div class="pagination">
<ul>
<?php
echo $this->Paginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
echo $this->Paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
?>
</ul>
</div>
</div>
<?php
echo $this->element('side_menu', array('menuList' => 'galaxies', 'menuItem' => 'index'));
?>

View File

@ -0,0 +1,33 @@
<?php
echo $this->element('side_menu', array('menuList' => 'galaxies', 'menuItem' => 'view'));
?>
<div class="galaxy view">
<div class="row-fluid">
<div class="span8">
<h2><?php echo h($galaxy['Galaxy']['name']); ?> galaxy</h2>
<dl>
<dt>Galaxy ID</dt>
<dd><?php echo h($galaxy['Galaxy']['id']); ?></dd>
<dt>Name</dt>
<dd><?php echo $galaxy['Galaxy']['name'] ? h($galaxy['Galaxy']['name']) : h($galaxy['Galaxy']['type']); ?></dd>
<dt>Uuid</dt>
<dd><?php echo h($galaxy['Galaxy']['uuid']); ?></dd>
<dt>Description</dt>
<dd><?php echo h($galaxy['Galaxy']['description']); ?></dd>
<dt>Version</dt>
<dd><?php echo h($galaxy['Galaxy']['version']); ?></dd>
</dl>
</div>
</div>
<div id="clusters_div">
<?php echo $this->element('galaxyclusters'); ?>
</div>
</div>
<script type="text/javascript">
$(document).ready(function () {
$.get("/galaxy_clusters/index/<?php echo $galaxy['Galaxy']['id']; ?>", function(data) {
$("#clusters_div").html(data);
});
});
</script>

View File

@ -0,0 +1,75 @@
<div class="pagination">
<ul>
<?php
$this->Paginator->options(array(
'update' => '#clusters_div',
'evalScripts' => true,
'before' => '$(".progress").show()',
'complete' => '$(".progress").hide()',
));
echo $this->Paginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
echo $this->Paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
?>
</ul>
</div>
<table class="table table-striped table-hover table-condensed">
<tr>
<th><?php echo $this->Paginator->sort('value');?></th>
<th><?php echo $this->Paginator->sort('synonyms');?></th>
<th>#Events</th>
<th><?php echo $this->Paginator->sort('description');?></th>
<th class="actions"><?php echo __('Actions');?></th>
</tr>
<?php
foreach ($list as $item):
?>
<tr>
<td class="short bold"><?php echo h($item['GalaxyCluster']['value']); ?>&nbsp;</td>
<td class="short bold">
<?php
echo nl2br(h(implode("\n", $item['GalaxyCluster']['synonyms'])));
?>
&nbsp;
</td>
<td class="short">
<?php
if ($item['GalaxyCluster']['tags']):
?>
<a href="<?php echo $baseurl; ?>/events/index/searchtag:<?php echo h($item['GalaxyCluster']['tags']['tag_id']);?>" class="bold"><?php echo h($item['GalaxyCluster']['tags']['count']);?></a>
<?php
else:
echo '0';
endif;
?>
</td>
<td><?php echo h($item['GalaxyCluster']['description']); ?>&nbsp;</td>
<td class="short action-links">
<?php echo $this->Html->link('', array('action' => 'view', $item['GalaxyCluster']['id']), array('class' => 'icon-list-alt', 'title' => 'View'));?>
</td>
</tr>
<?php
endforeach;
?>
</table>
<p>
<?php
echo $this->Paginator->counter(array('format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')));
?>
</p>
<div class="pagination">
<ul>
<?php
echo $this->Paginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
echo $this->Paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
?>
</ul>
</div>
<script type="text/javascript">
$(document).ready(function(){
});
</script>
<?php echo $this->Js->writeBuffer(); ?>

View File

@ -0,0 +1,59 @@
<?php
echo $this->element('side_menu', array('menuList' => 'galaxies', 'menuItem' => 'view_cluster'));
?>
<div class="galaxy view">
<div class="row-fluid">
<div class="span8">
<h2>
<?php echo isset($cluster['Galax']['name']) ? h($cluster['Galaxy']['name']) : h($cluster['GalaxyCluster']['type']) . ': ' . $cluster['GalaxyCluster']['value']; ?>
</h2>
<dl>
<dt>Cluster ID</dt>
<dd><?php echo h($cluster['GalaxyCluster']['id']); ?></dd>
<dt>Name</dt>
<dd><?php echo h($cluster['GalaxyCluster']['value']); ?></dd>
<dt>Parent Galaxy</dt>
<dd><?php echo $cluster['Galaxy']['name'] ? h($cluster['Galaxy']['name']) : h($cluster['Galaxy']['type']); ?></dd>
<dt>Description</dt>
<dd><?php echo h($cluster['GalaxyCluster']['description']); ?>&nbsp;</dd>
<dt>Source</dt>
<dd><?php echo h($cluster['GalaxyCluster']['source']); ?>&nbsp;</dd>
<dt>Authors</dt>
<dd>
<?php
$authors = json_decode($cluster['GalaxyCluster']['authors']);
if (!empty($authors)) {
echo implode(', ', $authors);
} else {
echo 'N/A';
}
?>
</dd>
<dt>Events</dt>
<dd>
<?php
if (isset($cluster['GalaxyCluster']['tag_count'])):
?>
<a href="<?php echo $baseurl; ?>/events/index/searchtag:<?php echo h($cluster['GalaxyCluster']['tag_id']); ?>"><?php echo h($cluster['GalaxyCluster']['tag_count']); ?> event(s)</a>
<?php
else:
echo '0';
endif;
?>
</dd>
</dl>
</div>
</div>
<div class="row-fluid">
<div id="elements_div" class="span8">
<?php echo $this->element('galaxyelements'); ?>
</div>
</div>
</div>
<script type="text/javascript">
$(document).ready(function () {
$.get("/galaxy_elements/index/<?php echo $cluster['GalaxyCluster']['id']; ?>", function(data) {
$("#elements_div").html(data);
});
});
</script>

View File

@ -0,0 +1,50 @@
<div class="pagination">
<ul>
<?php
$this->Paginator->options(array(
'update' => '#elements_div',
'evalScripts' => true,
'before' => '$(".progress").show()',
'complete' => '$(".progress").hide()',
));
echo $this->Paginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
echo $this->Paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
?>
</ul>
</div>
<div class="tabMenu tabMenuFiltersBlock noPrint" style="padding-right:0px !important;">
<span id="filter_header" class="attribute_filter_header">Filters: </span>AAA
</div>
<table class="table table-striped table-hover table-condensed">
<tr>
<th class="short"><?php echo $this->Paginator->sort('key');?></th>
<th><?php echo $this->Paginator->sort('value');?></th>
</tr>
<?php
foreach ($list as $item):
?>
<tr>
<td class="short"><?php echo h($item['GalaxyElement']['key']); ?>&nbsp;
</td><td class="short"><?php echo h($item['GalaxyElement']['value']); ?>&nbsp;</td>
</tr>
<?php
endforeach;
?>
</table>
<p>
<?php
echo $this->Paginator->counter(array('format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')));
?>
</p>
<div class="pagination">
<ul>
<?php
echo $this->Paginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
echo $this->Paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
?>
</ul>
</div>
<?php echo $this->Js->writeBuffer(); ?>

1
app/files/misp-galaxy Submodule

@ -0,0 +1 @@
Subproject commit 65b83f7305fc50d2d51f159f51d67e603704aae3

View File

@ -45,9 +45,9 @@ pre {
.navbar-lab .navbar-inner{
background: #FF9900;
-webkit-border-radius: 0px !important;
-moz-border-radius: 0px !important;
border-radius: 0px !important;
-webkit-border-radius: 0px !important;
-moz-border-radius: 0px !important;
border-radius: 0px !important;
}
.navbar-lab .nav > li > a{
@ -55,9 +55,9 @@ pre {
}
.navbar-inner{
-webkit-border-radius: 0px !important;
-moz-border-radius: 0px !important;
border-radius: 0px !important;
-webkit-border-radius: 0px !important;
-moz-border-radius: 0px !important;
border-radius: 0px !important;
}
/* MULTI-LEVEL DROPDOWNS FOR BOOTSTRAP */
@ -104,38 +104,38 @@ th.filter a {
}
td.searchLabel{
opacity: 50;
height: 20px;
padding-top: 4px;
padding-left: 4px;
padding-right: 4px;
vertical-align:top;
background-color: #F2F2F2;
box-shadow: 0px 0px 6px #B2B2B2;
opacity: 50;
height: 20px;
padding-top: 4px;
padding-left: 4px;
padding-right: 4px;
vertical-align:top;
background-color: #F2F2F2;
box-shadow: 0px 0px 6px #B2B2B2;
}
td.searchLabelFirst{
opacity: 50;
height: 20px;
padding-top: 4px;
padding-left: 4px;
padding-right: 4px;
vertical-align:top;
background-color: #F2F2F2;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
box-shadow: 0px 0px 6px #B2B2B2;
opacity: 50;
height: 20px;
padding-top: 4px;
padding-left: 4px;
padding-right: 4px;
vertical-align:top;
background-color: #F2F2F2;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
box-shadow: 0px 0px 6px #B2B2B2;
}
td.searchLabelCancel{
opacity: 50;
height: 20px;
width: 20px;
padding-top: 4px;
padding-left: 5px;
opacity: 50;
height: 20px;
width: 20px;
padding-top: 4px;
padding-left: 5px;
vertical-align:top;
background-color: #FFFFFF;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
box-shadow: 0px 0px 6px #B2B2B2;
background-color: #FFFFFF;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
box-shadow: 0px 0px 6px #B2B2B2;
}
.dropdown-menu{
@ -145,9 +145,9 @@ td.searchLabelCancel{
form .error-message {
border-color: #b94a48;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
background-color: #f2dede;
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
background-color: #f2dede;
}
@ -179,38 +179,38 @@ div.input{
div.forminfo{
font-size: 80%;
width: 220px;
opacity: 50;
margin-top: 0px;
margin-bottom: 10px;
width: 220px;
opacity: 50;
margin-top: 0px;
margin-bottom: 10px;
float: top;
background-color: #F2F2F2;
border-radius: 5px;
box-shadow: 0px 0px 6px #B2B2B2;
background-color: #F2F2F2;
border-radius: 5px;
box-shadow: 0px 0px 6px #B2B2B2;
}
div.visualisation{
font-size: 80%;
display: inline-block;
opacity: 50;
margin-top: 0px;
margin-bottom: 10px;
opacity: 50;
margin-top: 0px;
margin-bottom: 10px;
float: top;
background-color: #F2F2F2;
border-radius: 5px;
box-shadow: 5px 5px 6px #B2B2B2;
background-color: #F2F2F2;
border-radius: 5px;
box-shadow: 5px 5px 6px #B2B2B2;
}
div.message{
font-size: 133%;
opacity: 50;
margin-bottom: 15px;
padding: 5px;
opacity: 50;
margin-bottom: 15px;
padding: 5px;
float: top;
color: #FFFFFF;
background-color: #C11B17;
border-radius: 10px;
box-shadow: 5px 5px 8px #B2B2B2;
background-color: #C11B17;
border-radius: 10px;
box-shadow: 5px 5px 8px #B2B2B2;
}
.clear{
@ -479,8 +479,8 @@ dd {
position: absolute;
padding: 0;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
background: rgba(0,0,0,0.25);
box-shadow: 0 2px 6px rgba(0,0,0,0.5), inset 0 1px rgba(255,255,255,0.3), inset 0 10px rgba(255,255,255,0.1), inset 0 10px 20px rgba(255,255,255,0.3), inset 0 -15px 30px rgba(0,0,0,0.3);
}
@ -1184,7 +1184,7 @@ a.proposal_link_red:hover {
.templateTableRow {
width:100%;
display:inline-block;
box-shadow: 4px 2px 4px 2px #aaa;
box-shadow: 4px 2px 4px 2px #aaa;
margin: 0 0 15px 0;
background-color: #FFFFFF;
padding:0px !important;
@ -1290,8 +1290,8 @@ a.proposal_link_red:hover {
position: absolute;
padding: 0;
-webkit-border-radius: 7px 7px 0px 0px;
-moz-border-radius: 7px 7px 0px 0px;
border-radius: 7px 7px 0px 0px;
-moz-border-radius: 7px 7px 0px 0px;
border-radius: 7px 7px 0px 0px;
background: rgba(0,0,0,0.1.25);
box-shadow: 0 2px 6px rgba(0,0,0,0.5),
inset 0 1px rgba(255,255,255,0.3),
@ -1565,6 +1565,17 @@ a.discrete {
height: 100%;
}
.info_container {
border: 1px solid #0088cc;
border-radius: 7px;
box-shadow: 0px 0px 6px #B2B2B2;
padding-left:10px;
padding-right:10px;
padding-bottom:10px;
width: 100%;
height: 100%;
}
.bottomGap {
margin-bottom:5px;
}
@ -1577,27 +1588,27 @@ a.discrete {
}
.tooltip-inner {
white-space:pre-wrap !important;
white-space:pre-wrap !important;
}
.progress-queued .bar, .progress .bar-queued {
background-color: #A0A0A0;
background-image: -moz-linear-gradient(top, #dbdbdb, #bfbfbf);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#dbdbdb), to(#bfbfbf));
background-image: -webkit-linear-gradient(top, #dbdbdb, #bfbfbf);
background-image: -o-linear-gradient(top, #dbdbdb, #bfbfbf);
background-image: linear-gradient(to bottom, #dbdbdb, #bfbfbf);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffbfbfbf', GradientType=0);
background-color: #A0A0A0;
background-image: -moz-linear-gradient(top, #dbdbdb, #bfbfbf);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#dbdbdb), to(#bfbfbf));
background-image: -webkit-linear-gradient(top, #dbdbdb, #bfbfbf);
background-image: -o-linear-gradient(top, #dbdbdb, #bfbfbf);
background-image: linear-gradient(to bottom, #dbdbdb, #bfbfbf);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffbfbfbf', GradientType=0);
}
.progress-queued.progress-striped .bar, .progress-striped .bar-warning {
background-color: #A0A0A0;
background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-color: #A0A0A0;
background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
}
table.table.table-striped tr.deleted_row td {
@ -1605,6 +1616,17 @@ table.table.table-striped tr.deleted_row td {
color: white !important;
}
.caret-right {
border-bottom: 4px solid transparent;
border-top: 4px solid transparent;
border-left: 4px solid;
display: inline-block;
height: 0;
opacity: 0.3;
vertical-align: top;
width: 0;
}
@-webkit-keyframes rotation {
from {-webkit-transform: rotate(0deg);}
to {-webkit-transform: rotate(359deg);}

View File

@ -2688,3 +2688,26 @@ function selectAllInbetween(last, current) {
}
});
}
$('.galaxy-toggle-button').click(function() {
var element = $(this).data('toggle-type');
if ($(this).children('span').hasClass('icon-minus')) {
$(this).children('span').addClass('icon-plus');
$(this).children('span').removeClass('icon-minus');
$('#' + element + '_div').hide();
} else {
$(this).children('span').removeClass('icon-plus');
$(this).children('span').addClass('icon-minus');
$('#' + element + '_div').show();
}
});
$('#addGalaxy').click(function() {
getPopup($(this).data('event-id'), 'galaxies', 'selectGalaxy');
});
function quickSubmitGalaxyForm(event_id, cluster_id) {
$('#GalaxyTargetId').val(cluster_id);
$('#GalaxySelectClusterForm').submit();
return false;
}

View File

@ -16,6 +16,7 @@
"locked": false,
"publish_timestamp": "1418217647",
"sharing_group_id": "0",
"Galaxy": [],
"Org": {
"id": "2",
"name": "CIRCL",