Merge branch '2.4' of github.com:MISP/MISP into 2.4

pull/4037/head
chrisr3d 2019-01-20 19:36:04 +01:00
commit 43f1c3882b
74 changed files with 2520 additions and 933 deletions

View File

@ -1 +1 @@
{"major":2, "minor":4, "hotfix":100}
{"major":2, "minor":4, "hotfix":101}

View File

@ -179,6 +179,54 @@ class ServerShell extends AppShell
echo $outcome['message'] . PHP_EOL;
}
public function cacheServer() {
if (empty($this->args[0]) || empty($this->args[1])) {
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['cacheServer'] . PHP_EOL);
}
$userId = $this->args[0];
$user = $this->User->getAuthUser($userId);
if (empty($user)) die('Invalid user.' . PHP_EOL);
$scope = $this->args[1];
if (!empty($this->args[2])) {
$jobId = $this->args[2];
} else {
$this->Job->create();
$data = array(
'worker' => 'default',
'job_type' => 'cache_servers',
'job_input' => 'Server: ' . $id,
'status' => 0,
'retries' => 0,
'org' => $user['Organisation']['name'],
'message' => 'Starting server caching.',
);
$this->Job->save($data);
$jobId = $this->Job->id;
}
$this->Job->read(null, $jobId);
$result = $this->Server->cacheServerInitiator($user, $scope, $jobId);
$this->Job->id = $jobId;
if ($result !== true) {
$message = 'Job Failed. Reason: ';
$this->Job->save(array(
'id' => $jobId,
'message' => $message . $result,
'progress' => 0,
'status' => 3
));
} else {
$message = 'Job done.';
$this->Job->save(array(
'id' => $jobId,
'message' => $message,
'progress' => 100,
'status' => 4
));
}
echo $message . PHP_EOL;
}
public function cacheFeed() {
if (empty($this->args[0]) || empty($this->args[1])) {
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['cacheFeed'] . PHP_EOL);

View File

@ -46,7 +46,7 @@ class AppController extends Controller
public $helpers = array('Utility', 'OrgImg');
private $__queryVersion = '51';
private $__queryVersion = '53';
public $pyMispVersion = '2.4.99';
public $phpmin = '5.6.5';
public $phprec = '7.0.16';
@ -407,6 +407,7 @@ class AppController extends Controller
$this->set('me', $this->Auth->user());
$this->set('isAdmin', $role['perm_admin']);
$this->set('isSiteAdmin', $role['perm_site_admin']);
$this->set('hostOrgUser', $this->Auth->user('org_id') == Configure::read('MISP.host_org_id'));
$this->set('isAclAdd', $role['perm_add']);
$this->set('isAclModify', $role['perm_modify']);
$this->set('isAclModifyOrg', $role['perm_modify_org']);
@ -641,9 +642,17 @@ class AppController extends Controller
$options['additional_delimiters'] = array($options['additional_delimiters']);
}
foreach ($data as $k => $v) {
$data[$k] = explode($options['additional_delimiters'][0], str_replace($options['additional_delimiters'], $options['additional_delimiters'][0], $v));
foreach ($data[$k] as $k2 => $value) {
$data[$k][$k2] = trim($data[$k][$k2]);
$found = false;
foreach ($options['additional_delimiters'] as $delim) {
if (strpos($v, $delim) !== false) {
$found = true;
}
}
if ($found) {
$data[$k] = explode($options['additional_delimiters'][0], str_replace($options['additional_delimiters'], $options['additional_delimiters'][0], $v));
foreach ($data[$k] as $k2 => $value) {
$data[$k][$k2] = trim($data[$k][$k2]);
}
}
}
}

View File

@ -1462,12 +1462,11 @@ class AttributesController extends AppController
}
}
public function editSelected($id)
public function editSelected($id, $selectedAttributeIds = "[]")
{
if (!$this->request->is('ajax')) {
throw new MethodNotAllowedException(__('This method can only be accessed via AJAX.'));
}
if ($this->request->is('post')) {
$event = $this->Attribute->Event->find('first', array(
'conditions' => array('id' => $id),
@ -1488,7 +1487,18 @@ class AttributesController extends AppController
'recursive' => -1,
));
if ($this->request->data['Attribute']['to_ids'] == 2 && $this->request->data['Attribute']['distribution'] == 6 && $this->request->data['Attribute']['comment'] == null) {
$tags_ids_remove = json_decode($this->request->data['Attribute']['tags_ids_remove']);
$tags_ids_add = json_decode($this->request->data['Attribute']['tags_ids_add']);
$clusters_ids_remove = json_decode($this->request->data['Attribute']['clusters_ids_remove']);
$clusters_ids_add = json_decode($this->request->data['Attribute']['clusters_ids_add']);
$changeInTagOrCluster = ($tags_ids_remove !== null && count($tags_ids_remove) > 0)
|| ($tags_ids_add === null || count($tags_ids_add) > 0)
|| ($clusters_ids_remove === null || count($clusters_ids_remove) > 0)
|| ($clusters_ids_add === null || count($clusters_ids_add) > 0);
$changeInAttribute = ($this->request->data['Attribute']['to_ids'] != 2) || ($this->request->data['Attribute']['distribution'] != 6) || ($this->request->data['Attribute']['comment'] != null);
if (!$changeInAttribute && !$changeInTagOrCluster) {
$this->autoRender = false;
return new CakeResponse(array('body'=> json_encode(array('saved' => true)), 'status' => 200, 'type' => 'json'));
}
@ -1526,29 +1536,166 @@ class AttributesController extends AppController
$attributes[$key]['Attribute']['timestamp'] = $timestamp;
}
if ($this->Attribute->saveMany($attributes)) {
if (!$this->_isRest()) {
$this->Attribute->Event->insertLock($this->Auth->user(), $id);
if ($changeInAttribute) {
if ($this->Attribute->saveMany($attributes)) {
if (!$this->_isRest()) {
$this->Attribute->Event->insertLock($this->Auth->user(), $id);
}
$event['Event']['timestamp'] = $date->getTimestamp();
$event['Event']['published'] = 0;
$this->Attribute->Event->save($event, array('fieldList' => array('published', 'timestamp', 'info', 'id')));
$this->autoRender = false;
return new CakeResponse(array('body'=> json_encode(array('saved' => true)), 'status' => 200, 'type' => 'json'));
} else {
$this->autoRender = false;
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'validationErrors' => $this->Attribute->validationErrors)), 'status' => 200, 'type' => 'json'));
}
$event['Event']['timestamp'] = $date->getTimestamp();
$event['Event']['published'] = 0;
$this->Attribute->Event->save($event, array('fieldList' => array('published', 'timestamp', 'info', 'id')));
$this->autoRender = false;
return new CakeResponse(array('body'=> json_encode(array('saved' => true)), 'status' => 200, 'type' => 'json'));
} else {
$this->autoRender = false;
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'validationErrors' => $this->Attribute->validationErrors)), 'status' => 200, 'type' => 'json'));
}
// apply changes in tag/cluster
foreach ($attributes as $key => $attribute) {
foreach ($tags_ids_remove as $t => $tag_id) {
$this->removeTag($attributes[$key]['Attribute']['id'], $tag_id);
}
foreach ($tags_ids_add as $t => $tag_id) {
$this->addTag($attributes[$key]['Attribute']['id'], $tag_id);
}
$this->Galaxy = ClassRegistry::init('Galaxy');
foreach ($clusters_ids_remove as $c => $cluster_id) {
$this->Galaxy->detachCluster($this->Auth->user(), 'attribute', $attributes[$key]['Attribute']['id'], $cluster_id);
}
foreach ($clusters_ids_add as $c => $cluster_id) {
$this->Galaxy->attachCluster($this->Auth->user(), 'attribute', $attributes[$key]['Attribute']['id'], $cluster_id);
}
}
return new CakeResponse(array('body'=> json_encode(array('saved' => true)), 'status' => 200, 'type' => 'json'));
} else {
if (!isset($id)) {
throw new MethodNotAllowedException(__('No event ID provided.'));
}
$selectedAttributeIds = json_decode($selectedAttributeIds);
if ($selectedAttributeIds === null) {
$selectedAttributeIds = array();
}
App::uses('TextColourHelper', 'View/Helper');
$textColourHelper = new TextColourHelper(new View());
$tagTemplate = '<span href="#" class="tagComplete" style="background-color:{{=it.background}}; color:{{=it.color}}">{{=it.name}}</span>';
$galaxyTemplate = '<span href="#" class="tagComplete" style="background-color:{{=it.background}}; color:{{=it.color}}">{{=it.name}}</span>';
// tags to remove
$tags = $this->Attribute->AttributeTag->getAttributesTags($this->Auth->user(), $id, $selectedAttributeIds);
$tagItemsRemove = array();
foreach ($tags as $k => $tag) {
$tagName = $tag['name'];
$tagItemsRemove[] = array(
'name' => h($tagName),
'value' => h($tag['id']),
'template' => $tagTemplate,
'templateData' => array(
'name' => h($tagName),
'background' => h(isset($tag['colour']) ? $tag['colour'] : '#ffffff'),
'color' => h(isset($tag['colour']) ? $textColourHelper->getTextColour($tag['colour']) : '#0088cc')
),
);
}
unset($tags);
// clusters to remove
$clusters = $this->Attribute->AttributeTag->getAttributesClusters($this->Auth->user(), $id, $selectedAttributeIds);
$clusterItemsRemove = array();
foreach ($clusters as $k => $cluster) {
$clusterTemplate = '{{=it.name}}';
if (strlen($cluster['description']) < 50) {
$clusterTemplate .= '<i style="float:right; font-size: smaller;">{{=it.description}}</i>';
} else {
$clusterTemplate .= '<it class="fa fa-info-circle" style="float:right;" title="{{=it.description}}"></it>';
}
if ($cluster['synonyms_string'] !== "") {
$clusterTemplate .= '<div class="apply_css_arrow" style="padding-left: 5px; font-size: smaller;"><i>{{=it.synonyms_string}}</i></div>';
}
$title = __('Synonyms: ') . h($cluster['synonyms_string']);
$name = h($cluster['value']);
$optionName = h($cluster['value']);
$optionName .= $cluster['synonyms_string'] !== '' ? ' (' . h($cluster['synonyms_string']) . ')' : '';
$clusterItemsRemove[] = array(
'name' => $optionName,
'value' => h($cluster['id']),
'additionalData' => array(
'event_id' => h($id),
),
'template' => $clusterTemplate,
'templateData' => array(
'name' => $name,
'description' => h($cluster['description']),
'synonyms_string' => $title
)
);
}
unset($clusters);
$conditions = array();
if (!$this->_isSiteAdmin()) {
$conditions = array('Tag.org_id' => array(0, $this->Auth->user('org_id')));
$conditions = array('Tag.user_id' => array(0, $this->Auth->user('id')));
$conditions = array('Tag.hide_tag' => 0);
}
$allTags = $this->Attribute->AttributeTag->Tag->find('all', array('conditions' => $conditions, 'recursive' => -1));
$tags = array();
foreach ($allTags as $i => $tag) {
$tags[$tag['Tag']['id']] = $tag['Tag'];
}
unset($allTags);
$tagItemsAdd = array();
foreach ($tags as $k => $tag) {
$tagName = $tag['name'];
$tagItemsAdd[] = array(
'name' => h($tagName),
'value' => h($tag['id']),
'template' => $tagTemplate,
'templateData' => array(
'name' => h($tagName),
'background' => h(isset($tag['colour']) ? $tag['colour'] : '#ffffff'),
'color' => h(isset($tag['colour']) ? $textColourHelper->getTextColour($tag['colour']) : '#0088cc')
),
);
}
// clusters to add
$this->GalaxyCluster = ClassRegistry::init('GalaxyCluster');
$clusters = $this->GalaxyCluster->find('all', array(
'fields' => array('value', 'id'),
'recursive' => -1
));
$clusterItemsAdd = array();
foreach ($clusters as $k => $cluster) {
$clusterItemsAdd[] = array(
'name' => $cluster['GalaxyCluster']['value'],
'value' => $cluster['GalaxyCluster']['id']
);
}
unset($clusters);
$this->layout = 'ajax';
$this->set('id', $id);
$this->set('sgs', $this->Attribute->SharingGroup->fetchAllAuthorised($this->Auth->user(), 'name', true));
$this->set('distributionLevels', $this->Attribute->distributionLevels);
$this->set('distributionDescriptions', $this->Attribute->distributionDescriptions);
$this->set('attrDescriptions', $this->Attribute->fieldDescriptions);
$this->set('tagItemsRemove', $tagItemsRemove);
$this->set('tagItemsAdd', $tagItemsAdd);
$this->set('clusterItemsAdd', $clusterItemsAdd);
$this->set('clusterItemsRemove', $clusterItemsRemove);
$this->set('options', array( // set chosen (select picker) options
'multiple' => -1,
'disabledSubmitButton' => true,
'flag_redraw_chosen' => true
));
$this->render('ajax/attributeEditMassForm');
}
}
@ -1578,7 +1725,7 @@ class AttributesController extends AppController
$this->set('typeDefinitions', $this->Attribute->typeDefinitions);
$this->set('categoryDefinitions', $this->Attribute->categoryDefinitions);
$this->set('shortDist', $this->Attribute->shortDist);
if ($this->request->is('post')) {
if ($this->request->is('post') || !empty($this->request->params['named']['tags'])) {
if (isset($this->request->data['Attribute'])) {
$this->request->data = $this->request->data['Attribute'];
}
@ -1659,6 +1806,25 @@ class AttributesController extends AppController
} else {
return $this->RestResponse->viewData($attributes, $this->response->type());
}
if (isset($filters['tags']) && !empty($filters['tags'])) {
// if the tag is passed by ID - show its name in the view
$this->loadModel('Tag');
if (!is_array($filters['tags'])) {
$filters['tags'] = array($filters['tags']);
}
foreach ($filters['tags'] as $k => &$v) {
if (!is_numeric($v))
continue;
$tag = $this->Tag->find('first', [
'conditions' => ['Tag.id' => $v],
'fields' => ['name'],
'recursive' => -1
]);
if (!empty($tag)) {
$v = $tag['Tag']['name'];
}
}
}
$this->set('filters', $filters);
$this->set('attributes', $attributes);
$this->set('isSearch', 1);
@ -2850,11 +3016,33 @@ class AttributesController extends AppController
$tag_id_list[] = $tagCollectionTag['tag_id'];
}
} else {
$tag = $this->Event->EventTag->Tag->find('first', array('recursive' => -1, 'conditions' => $conditions));
if (empty($tag)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status'=>200, 'type' => 'json'));
// try to parse json array
$tag_ids = json_decode($tag_id);
if ($tag_ids !== null) { // can decode json
$tag_id_list = array();
foreach ($tag_ids as $tag_id) {
if (preg_match('/^collection_[0-9]+$/i', $tag_id)) {
$tagChoice = explode('_', $tag_id)[1];
$this->loadModel('TagCollection');
$tagCollection = $this->TagCollection->fetchTagCollection($this->Auth->user(), array('conditions' => array('TagCollection.id' => $tagChoice)));
if (empty($tagCollection)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag Collection.')), 'status'=>200, 'type' => 'json'));
}
$tag_id_list = array();
foreach ($tagCollection[0]['TagCollectionTag'] as $tagCollectionTag) {
$tag_id_list[] = $tagCollectionTag['tag_id'];
}
} else {
$tag_id_list[] = $tag_id;
}
}
} else {
$tag = $this->Event->EventTag->Tag->find('first', array('recursive' => -1, 'conditions' => $conditions));
if (empty($tag)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status'=>200, 'type' => 'json'));
}
$tag_id = $tag['Tag']['id'];
}
$tag_id = $tag['Tag']['id'];
}
}
if (!isset($idList)) {

View File

@ -139,6 +139,7 @@ class ACLComponent extends Component
'stix2' => array('*'),
'strposarray' => array(),
'toggleCorrelation' => array('perm_add'),
'unpublish' => array('perm_modify'),
'updateGraph' => array('*'),
'upload_analysis_file' => array('perm_add'),
'upload_sample' => array('AND' => array('perm_auth', 'perm_add')),
@ -158,7 +159,7 @@ class ACLComponent extends Component
'feeds' => array(
'add' => array(),
'cacheFeeds' => array(),
'compareFeeds' => array(),
'compareFeeds' => array('*'),
'delete' => array(),
'disable' => array(),
'edit' => array(),
@ -168,11 +169,11 @@ class ACLComponent extends Component
'fetchSelectedFromFreetextIndex' => array(),
'getEvent' => array(),
'importFeeds' => array(),
'index' => array(),
'previewEvent' => array(),
'previewIndex' => array(),
'index' => array('*'),
'previewEvent' => array('*'),
'previewIndex' => array('*'),
'toggleSelected' => array('perm_site_admin'),
'view' => array(),
'view' => array('*'),
),
'galaxies' => array(
'attachCluster' => array('perm_tagger'),
@ -254,6 +255,7 @@ class ACLComponent extends Component
'delete' => array('perm_object_template'),
'getToggleField' => array(),
'objectChoice' => array('*'),
'objectMetaChoice' => array('perm_add'),
'view' => array('*'),
'viewElements' => array('*'),
'index' => array('*'),
@ -310,6 +312,7 @@ class ACLComponent extends Component
),
'servers' => array(
'add' => array(),
'cache' => array('perm_site_admin'),
'checkout' => array(),
'delete' => array(),
'deleteFile' => array(),

View File

@ -1414,10 +1414,18 @@ class EventsController extends AppController
} else {
$this->set('extended', 0);
}
$conditions['includeFeedCorrelations'] = true;
$conditions['includeFeedCorrelations'] = 1;
if (!$this->_isRest()) {
$conditions['includeGranularCorrelations'] = 1;
}
if (!isset($this->params['named']['includeServerCorrelations'])) {
$conditions['includeServerCorrelations'] = 1;
if ($this->_isRest()) {
$conditions['includeServerCorrelations'] = 0;
}
} else {
$conditions['includeServerCorrelations'] = $this->params['named']['includeServerCorrelations'];
}
$results = $this->Event->fetchEvent($this->Auth->user(), $conditions);
if (empty($results)) {
throw new NotFoundException(__('Invalid event'));
@ -2145,6 +2153,42 @@ class EventsController extends AppController
}
}
public function unpublish($id = null)
{
$this->Event->id = $id;
if (!$this->Event->exists()) {
throw new NotFoundException(__('Invalid event'));
}
$this->Event->recursive = -1;
$event = $this->Event->read(null, $id);
if (!$this->_isSiteAdmin()) {
if (!$this->userRole['perm_modify'] || $this->Auth->user('org_id') !== $this->Event->data['Event']['orgc_id']) {
throw new MethodNotAllowedException(__('You don\'t have the permission to do that.'));
}
}
$this->Event->insertLock($this->Auth->user(), $id);
if ($this->request->is('post') || $this->request->is('put')) {
$fieldList = array('published', 'id', 'info');
$event['Event']['published'] = 0;
$result = $this->Event->save($event, array('fieldList' => $fieldList));
if ($result) {
$message = __('Event unpublished.');
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('events', 'unpublish', $id, false, $message);
} else {
$this->Flash->success($message);
$this->redirect(array('action' => 'view', $id));
}
} else {
throw new MethodNotAllowedException('Could not unpublish event.');
}
} else {
$this->set('id', $id);
$this->set('type', 'unpublish');
$this->render('ajax/eventPublishConfirmationForm');
}
}
// Publishes the event without sending an alert email
public function publish($id = null)
{
@ -3330,11 +3374,32 @@ class EventsController extends AppController
$tag_id_list[] = $tagCollectionTag['tag_id'];
}
} else {
$tag = $this->Event->EventTag->Tag->find('first', array('recursive' => -1, 'conditions' => $conditions));
if (empty($tag)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status'=>200, 'type' => 'json'));
$tag_ids = json_decode($tag_id);
if ($tag_ids !== null) { // can decode json
$tag_id_list = array();
foreach ($tag_ids as $tag_id) {
if (preg_match('/^collection_[0-9]+$/i', $tag_id)) {
$tagChoice = explode('_', $tag_id)[1];
$this->loadModel('TagCollection');
$tagCollection = $this->TagCollection->fetchTagCollection($this->Auth->user(), array('conditions' => array('TagCollection.id' => $tagChoice)));
if (empty($tagCollection)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag Collection.')), 'status'=>200, 'type' => 'json'));
}
$tag_id_list = array();
foreach ($tagCollection[0]['TagCollectionTag'] as $tagCollectionTag) {
$tag_id_list[] = $tagCollectionTag['tag_id'];
}
} else {
$tag_id_list[] = $tag_id;
}
}
} else {
$tag = $this->Event->EventTag->Tag->find('first', array('recursive' => -1, 'conditions' => $conditions));
if (empty($tag)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status'=>200, 'type' => 'json'));
}
$tag_id = $tag['Tag']['id'];
}
$tag_id = $tag['Tag']['id'];
}
}
$this->Event->recursive = -1;
@ -4556,7 +4621,7 @@ class EventsController extends AppController
return new CakeResponse(array('body' => json_encode($json), 'status' => 200, 'type' => 'json'));
}
public function viewMitreAttackMatrix($eventId, $itemType='event', $itemId=false)
public function viewMitreAttackMatrix($scope_id, $scope='event', $disable_picking=false)
{
$this->loadModel('Galaxy');
@ -4566,6 +4631,24 @@ class EventsController extends AppController
$killChainOrders = $attackTacticData['killChain'];
$instanceUUID = $attackTacticData['instance-uuid'];
if ($scope == 'event') {
$eventId = $scope_id;
} elseif ($scope == 'attribute') {
$attribute = $this->Event->Attribute->fetchAttributes($this->Auth->user(), array(
'conditions' => array('Attribute.id' => $scope_id),
'fields' => array('event_id')
));
if (empty($attribute)) {
throw new Exception("Invalid Attribute.");
}
$attribute = $attribute[0];
$eventId = $attribute['Attribute']['event_id'];
} elseif ($scope == 'tag_collection') {
$eventId = 0; // no event_id for tag_collection, consider all events
} else {
throw new Exception("Invalid options.");
}
$scoresDataAttr = $this->Event->Attribute->AttributeTag->getTagScores($eventId, $attackTags);
$scoresDataEvent = $this->Event->EventTag->getTagScores($eventId, $attackTags);
$scoresData = array();
@ -4589,20 +4672,15 @@ class EventsController extends AppController
$colours = $gradientTool->createGradientFromValues($scores);
$this->set('eventId', $eventId);
$this->set('target_type', $itemType);
$this->set('target_type', $scope);
$this->set('killChainOrders', $killChainOrders);
$this->set('attackTactic', $attackTactic);
$this->set('scores', $scores);
$this->set('maxScore', $maxScore);
$this->set('colours', $colours);
// picking mode
if ($itemId !== false) {
$this->set('pickingMode', true);
$this->set('target_id', $itemId);
} else {
$this->set('pickingMode', false);
}
$this->set('pickingMode', !$disable_picking);
$this->set('target_id', $scope_id);
$this->render('/Elements/view_mitre_attack_matrix');
}
}

View File

@ -23,13 +23,16 @@ class FeedsController extends AppController
{
parent::beforeFilter();
$this->Security->unlockedActions = array('previewIndex');
if (!$this->_isSiteAdmin()) {
if (!$this->_isSiteAdmin() && $this->Auth->user('org_id') != Configure::read('MISP.host_org_id')) {
throw new MethodNotAllowedException(__('You don\'t have the required privileges to do that.'));
}
}
public function index()
{
if (!$this->_isSiteAdmin() && !$this->Auth->user('org_id') == Configure::read('MISP.host_org_id')) {
throw NotAllowedException('You don\'t have access to this feature.');
}
$this->Feed->load_default_feeds();
$scope = isset($this->passedArgs['scope']) ? $this->passedArgs['scope'] : 'all';
if ($scope !== 'all') {
@ -77,6 +80,9 @@ class FeedsController extends AppController
public function view($feedId)
{
if (!$this->_isSiteAdmin() && !$this->Auth->user('org_id') == Configure::read('MISP.host_org_id')) {
throw NotAllowedException('You don\'t have access to this feature.');
}
$feed = $this->Feed->find('first', array(
'conditions' => array('Feed.id' => $feedId),
'recursive' => -1,
@ -500,6 +506,9 @@ class FeedsController extends AppController
public function previewIndex($feedId)
{
if (!$this->_isSiteAdmin() && !$this->Auth->user('org_id') == Configure::read('MISP.host_org_id')) {
throw NotAllowedException('You don\'t have access to this feature.');
}
$this->Feed->id = $feedId;
if (!$this->Feed->exists()) {
throw new NotFoundException(__('Invalid feed.'));
@ -680,6 +689,9 @@ class FeedsController extends AppController
public function previewEvent($feedId, $eventUuid, $all = false)
{
if (!$this->_isSiteAdmin() && !$this->Auth->user('org_id') == Configure::read('MISP.host_org_id')) {
throw NotAllowedException('You don\'t have access to this feature.');
}
$this->Feed->id = $feedId;
if (!$this->Feed->exists()) {
throw new NotFoundException(__('Invalid feed.'));
@ -839,6 +851,9 @@ class FeedsController extends AppController
public function compareFeeds($id = false)
{
if (!$this->_isSiteAdmin() && !$this->Auth->user('org_id') == Configure::read('MISP.host_org_id')) {
throw NotAllowedException('You don\'t have access to this feature.');
}
$feeds = $this->Feed->compareFeeds($id);
if ($this->_isRest()) {
return $this->RestResponse->viewData($feeds, $this->response->type());

View File

@ -94,6 +94,7 @@ class GalaxiesController extends AppController
$galaxies = $this->Galaxy->find('all', array(
'recursive' => -1,
'conditions' => $conditions,
'order' => array('name asc')
));
if (!empty($tacticGalaxies)) {
array_unshift($galaxies, array('Galaxy' => array(
@ -105,10 +106,45 @@ class GalaxiesController extends AppController
'namespace' => 'mitre-attack'
)));
}
$this->set('galaxies', $galaxies);
$this->set('target_id', $target_id);
$this->set('target_type', $target_type);
$this->render('ajax/galaxy_choice');
$items = array();
$items[] = array(
'name' => __('All clusters'),
'value' => "/galaxies/selectCluster/" . h($target_id) . '/' . h($target_type) . '/0'
);
foreach ($galaxies as $galaxy) {
if ($galaxy['Galaxy']['id'] != -1) {
// construct option template
$galaxyTemplate = '<it class="fa fa-{{=it.icon}}" style="width: 22px;"></it>';
$galaxyTemplate .= '{{=it.name}}';
if (strlen($galaxy['Galaxy']['description']) < 50) {
$galaxyTemplate .= '<i style="float:right; font-size: smaller;">{{=it.description}}</i>';
} else {
$galaxyTemplate .= '<it class="fa fa-info-circle" style="float:right;" title="{{=it.description}}"></it>';
}
$items[] = array(
'name' => h($galaxy['Galaxy']['name']),
'value' => "/galaxies/selectCluster/" . h($target_id) . '/' . h($target_type) . '/' . h($galaxy['Galaxy']['id']),
'template' => $galaxyTemplate,
'templateData' => array(
'icon' => h($galaxy['Galaxy']['icon']),
'name' => h($galaxy['Galaxy']['name']),
'description' => h($galaxy['Galaxy']['description'])
)
);
} else { // attackMatrix
$items[] = array(
'name' => $galaxy['Galaxy']['name'],
'functionName' => "getMitreMatrixPopup('" . h($target_type) . "', '" . h($target_id) . "')",
'isPill' => true,
'img' => "/img/mitre-attack-icon.ico",
);
}
}
$this->set('items', $items);
$this->render('/Elements/generic_picker');
}
public function selectGalaxyNamespace($target_id, $target_type='event')
@ -116,12 +152,27 @@ class GalaxiesController extends AppController
$namespaces = $this->Galaxy->find('list', array(
'recursive' => -1,
'fields' => array('namespace', 'namespace'),
'group' => array('namespace')
'group' => array('namespace'),
'order' => array('namespace asc')
));
$this->set('namespaces', $namespaces);
$this->set('target_id', $target_id);
$this->set('target_type', $target_type);
$this->render('ajax/galaxy_namespace_choice');
$items = array();
$items[] = array(
'name' => __('All namespaces'),
'value' => "/galaxies/selectGalaxy/" . h($target_id) . '/' . h($target_type) . '/0'
);
foreach ($namespaces as $namespace) {
$items[] = array(
'name' => h($namespace),
'value' => "/galaxies/selectGalaxy/" . h($target_id) . '/' . h($target_type) . '/' . h($namespace)
);
}
$this->set('items', $items);
$this->set('options', array( // set chosen (select picker) options
'multiple' => 0,
));
$this->render('/Elements/generic_picker');
}
public function selectCluster($target_id, $target_type = 'event', $selectGalaxy = false)
@ -138,34 +189,67 @@ class GalaxiesController extends AppController
'conditions' => array('GalaxyElement.key' => 'synonyms')
)
),
'order' => array('value asc'),
'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[$cluster['GalaxyCluster']['type']][$element['value']])) {
$lookup_table[$cluster['GalaxyCluster']['type']][$element['value']][] = $cluster['GalaxyCluster']['id'];
} else {
$lookup_table[$cluster['GalaxyCluster']['type']][$element['value']] = array($cluster['GalaxyCluster']['id']);
}
}
$cluster['GalaxyCluster']['synonyms_string'] = implode(', ', $cluster['GalaxyCluster']['synonyms_string']);
unset($cluster['GalaxyElement']);
$clusters[$cluster['GalaxyCluster']['type']][$cluster['GalaxyCluster']['value']] = $cluster['GalaxyCluster'];
if (isset($lookup_table[$cluster['GalaxyCluster']['type']][$cluster['GalaxyCluster']['value']])) {
$lookup_table[$cluster['GalaxyCluster']['type']][$cluster['GalaxyCluster']['value']][] = $cluster['GalaxyCluster']['id'];
} else {
$lookup_table[$cluster['GalaxyCluster']['type']][$cluster['GalaxyCluster']['value']] = array($cluster['GalaxyCluster']['id']);
}
}
ksort($clusters);
$this->set('clusters', $clusters);
$this->set('target_id', $target_id);
$this->set('target_type', $target_type);
$this->set('lookup_table', $lookup_table);
$items = array();
foreach ($clusters as $namespace => $cluster_data) {
foreach ($cluster_data as $k => $cluster) {
$clusterTemplate = '{{=it.name}}';
if (strlen($cluster['description']) < 50) {
$clusterTemplate .= '<i style="float:right; font-size: smaller;">{{=it.description}}</i>';
} else {
$clusterTemplate .= '<it class="fa fa-info-circle" style="float:right;" title="{{=it.description}}"></it>';
}
if ($cluster['synonyms_string'] !== "") {
$clusterTemplate .= '<div class="apply_css_arrow" style="padding-left: 5px; font-size: smaller;"><i>{{=it.synonyms_string}}</i></div>';
}
$target_type = h($target_type);
$target_id = h($target_id);
$cluster_id = h($cluster['id']);
$title = __('Synonyms: ') . h($cluster['synonyms_string']);
$name = h($cluster['value']);
$optionName = h($cluster['value']);
$optionName .= $cluster['synonyms_string'] !== '' ? ' (' . h($cluster['synonyms_string']) . ')' : '';
$items[] = array(
'name' => $optionName,
'value' => h($cluster_id),
'title' => $title,
'additionalData' => array(
'target_id' => $target_id,
'target_type' => $target_type,
),
'template' => $clusterTemplate,
'templateData' => array(
'name' => $name,
'description' => h($cluster['description']),
'synonyms_string' => $title
)
);
}
}
$onClickForm = 'quickSubmitGalaxyForm';
$this->set('items', $items);
$this->set('options', array( // set chosen (select picker) options
'functionName' => $onClickForm,
'multiple' => '-1',
));
$this->render('ajax/cluster_choice');
}
@ -178,13 +262,35 @@ class GalaxiesController extends AppController
public function attachMultipleClusters($target_id, $target_type = 'event')
{
$cluster_ids = json_decode($this->request->data['Galaxy']['target_ids'], true);
$result = "";
foreach ($cluster_ids as $cluster_id) {
$result = $this->Galaxy->attachCluster($this->Auth->user(), $target_type, $target_id, $cluster_id);
if ($target_id === 'selected') {
$target_id_list = json_decode($this->request->data['Galaxy']['attribute_ids']);
} else {
$target_id_list = array($target_id);
}
$cluster_ids = $this->request->data['Galaxy']['target_ids'];
if (!empty($cluster_ids)) {
$cluster_ids = json_decode($cluster_ids, true);
if ($cluster_ids === null) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'error' => __('Failed to parse request.'))), 'status'=>200, 'type' => 'json'));
}
} else {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'error' => __('No clusters picked.'))), 'status'=>200, 'type' => 'json'));
}
$result = "";
if (!is_array($cluster_ids)) { // in case we only want to attach 1
$cluster_ids = array($cluster_ids);
}
foreach ($cluster_ids as $cluster_id) {
foreach ($target_id_list as $target_id) {
$result = $this->Galaxy->attachCluster($this->Auth->user(), $target_type, $target_id, $cluster_id);
}
}
if ($this->request->is('ajax')) {
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => $result, 'check_publish' => true)), 'status'=>200, 'type' => 'json'));
} else {
$this->Flash->info($result);
$this->redirect($this->referer());
}
$this->Flash->info($result);
$this->redirect($this->referer());
}
public function viewGraph($id)
@ -223,6 +329,12 @@ class GalaxiesController extends AppController
throw new MethodNotAllowedException('Invalid attribute.');
}
$object[0] = $this->Attribute->Event->massageTags($object[0], 'Attribute');
} elseif ($scope == 'tag_collection') {
$this->loadModel('TagCollection');
$object = $this->TagCollection->fetchTagCollection($this->Auth->user(), array('conditions' => array('TagCollection.id' => $id)));
if (empty($object)) {
throw new MethodNotAllowedException('Invalid Tag Collection.');
}
}
$this->set('object', $object[0]);
$this->render('/Events/ajax/ajaxGalaxies');

View File

@ -222,20 +222,40 @@ class GalaxyClustersController extends AppController
$event_id = $attribute['Attribute']['event_id'];
} elseif ($target_type == 'event') {
$event_id = $target_id;
} elseif ($target_type === 'tag_collection') {
// pass
} else {
throw new MethodNotAllowedException('Invalid options');
}
$this->Event->id = $event_id;
$this->Event->recursive = -1;
$event = $this->Event->read(array(), $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'])) {
if ($target_type === 'tag_collection') {
$tag_collection = $this->GalaxyCluster->Tag->TagCollectionTag->TagCollection->fetchTagCollection($this->Auth->user(), array(
'conditions' => array('TagCollection.id' => $target_id),
'contain' => array('Organisation', 'TagCollectionTag' => array('Tag'))
));
if (empty($tag_collection)) {
throw new MethodNotAllowedException('Invalid Tag Collection');
}
$tag_collection = $tag_collection[0];
if (!$this->_isSiteAdmin()) {
if (!$this->userRole['perm_tag_editor'] || $this->Auth->user('org_id') !== $tag_collection['TagCollection']['org_id']) {
throw new MethodNotAllowedException('Invalid Tag Collection');
}
}
} else {
$this->Event->id = $event_id;
$this->Event->recursive = -1;
$event = $this->Event->read(array(), $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.');
}
}
}
if ($target_type == 'attribute') {
$existingTargetTag = $this->Event->Attribute->AttributeTag->find('first', array(
'conditions' => array('AttributeTag.tag_id' => $tag_id, 'AttributeTag.attribute_id' => $target_id),
@ -248,6 +268,12 @@ class GalaxyClustersController extends AppController
'recursive' => -1,
'contain' => array('Tag')
));
} elseif ($target_type == 'tag_collection') {
$existingTargetTag = $this->GalaxyCluster->Tag->TagCollectionTag->find('first', array(
'conditions' => array('TagCollectionTag.tag_id' => $tag_id, 'TagCollectionTag.tag_collection_id' => $target_id),
'recursive' => -1,
'contain' => array('Tag')
));
}
if (empty($existingTargetTag)) {
@ -261,6 +287,8 @@ class GalaxyClustersController extends AppController
$result = $this->Event->EventTag->delete($existingTargetTag['EventTag']['id']);
} elseif ($target_type == 'attribute') {
$result = $this->Event->Attribute->AttributeTag->delete($existingTargetTag['AttributeTag']['id']);
} elseif ($target_type == 'tag_collection') {
$result = $this->GalaxyCluster->Tag->TagCollectionTag->delete($existingTargetTag['TagCollectionTag']['id']);
}
if ($result) {
$event['Event']['published'] = 0;

View File

@ -17,32 +17,80 @@ class ObjectTemplatesController extends AppController
'recursive' => -1
);
public function objectChoice($event_id)
{
$this->ObjectTemplate->populateIfEmpty($this->Auth->user());
$templates_raw = $this->ObjectTemplate->find('all', array(
public function objectMetaChoice($event_id) {
$metas = $this->ObjectTemplate->find('list', array(
'recursive' => -1,
'conditions' => array('ObjectTemplate.active' => 1),
'fields' => array('meta-category'),
'group' => array('ObjectTemplate.meta-category'),
'order' => array('ObjectTemplate.meta-category asc')
));
$items = array();
$items[] = array(
'name' => __('All Objects'),
'value' => "/ObjectTemplates/objectChoice/" . h($event_id) . "/" . "0"
);
foreach($metas as $meta) {
$items[] = array(
'name' => $meta,
'value' => "/ObjectTemplates/objectChoice/" . h($event_id) . "/" . h($meta)
);
}
$this->set('items', $items);
$this->set('options', array(
'multiple' => 0,
));
$this->render('/Elements/generic_picker');
}
public function objectChoice($event_id, $category=false)
{
$this->ObjectTemplate->populateIfEmpty($this->Auth->user());
$conditions = array('ObjectTemplate.active' => 1);
if ($category !== false && $category !== "0") {
$conditions['meta-category'] = $category;
}
$templates_raw = $this->ObjectTemplate->find('all', array(
'recursive' => -1,
'conditions' => $conditions,
'fields' => array('id', 'meta-category', 'name', 'description', 'org_id'),
'contain' => array('Organisation.name'),
'order' => array('ObjectTemplate.name asc')
));
$templates = array('all' => array());
foreach ($templates_raw as $k => $template) {
unset($template['ObjectTemplate']['meta-category']);
$template['ObjectTemplate']['org_name'] = $template['Organisation']['name'];
$templates[$templates_raw[$k]['ObjectTemplate']['meta-category']][] = $template['ObjectTemplate'];
$templates['all'][] = $template['ObjectTemplate'];
$items = array();
foreach($templates_raw as $template) {
$template = $template['ObjectTemplate'];
$chosenTemplate = '<span href="#">{{=it.name}}</span>';
if (strlen($template['description']) < 80) {
$chosenTemplate .= '<i style="float:right; font-size: smaller;">{{=it.description}}</i>';
} else {
$chosenTemplate .= '<it class="fa fa-info-circle" style="float:right;" title="{{=it.description}}"></it>';
}
$chosenTemplate .= '<div class="apply_css_arrow" style="padding-left: 5px; margin-top: 5px; font-size: smaller;"><i>{{=it.metacateg}}</i></div>';
$items[] = array(
'name' => $template['name'],
'value' => $template['id'],
'additionalData' => array('event_id' => h($event_id)),
'template' => $chosenTemplate,
'templateData' => array(
'name' => h($template['name']),
'description' => h($template['description']),
'metacateg' => __('Category') . ': ' . h($template['meta-category'])
)
);
}
foreach ($templates as $category => $template_list) {
$templates[$category] = Hash::sort($templates[$category], '{n}.name');
}
$template_categories = array_keys($templates);
$this->layout = false;
$this->set('template_categories', $template_categories);
$this->set('eventId', $event_id);
$this->set('templates', $templates);
$this->render('ajax/object_choice');
$fun = 'redirectAddObject';
$this->set('items', $items);
$this->set('options', array(
'functionName' => $fun,
'multiple' => 0,
));
$this->render('/Elements/generic_picker');
}
public function view($id)

View File

@ -54,14 +54,24 @@ class ServersController extends AppController
$params = array(
'recursive' => -1,
'contain' => array(
'Organisation' => array('Organisation.id', 'Organisation.name', 'Organisation.uuid', 'Organisation.nationality', 'Organisation.sector', 'Organisation.type'),
'RemoteOrg' => array('RemoteOrg.id', 'RemoteOrg.name', 'RemoteOrg.uuid', 'RemoteOrg.nationality', 'RemoteOrg.sector', 'RemoteOrg.type'),
)
'User' => array(
'fields' => array('User.id', 'User.org_id', 'User.email'),
),
'Organisation' => array(
'fields' => array('Organisation.id', 'Organisation.name', 'Organisation.uuid', 'Organisation.nationality', 'Organisation.sector', 'Organisation.type'),
),
'RemoteOrg' => array(
'fields' => array('RemoteOrg.id', 'RemoteOrg.name', 'RemoteOrg.uuid', 'RemoteOrg.nationality', 'RemoteOrg.sector', 'RemoteOrg.type'),
),
),
);
$servers = $this->Server->find('all', $params);
$servers = $this->Server->attachServerCacheTimestamps($servers);
return $this->RestResponse->viewData($servers, $this->response->type());
} else {
$this->set('servers', $this->paginate());
$servers = $this->paginate();
$servers = $this->Server->attachServerCacheTimestamps($servers);
$this->set('servers', $servers);
$collection = array();
$collection['orgs'] = $this->Server->Organisation->find('list', array(
'fields' => array('id', 'name'),
@ -236,6 +246,7 @@ class ServersController extends AppController
$defaults = array(
'push' => 0,
'pull' => 0,
'caching_enabled' => 0,
'json' => '[]',
'push_rules' => '[]',
'pull_rules' => '[]',
@ -422,7 +433,7 @@ class ServersController extends AppController
}
if (!$fail) {
// say what fields are to be updated
$fieldList = array('id', 'url', 'push', 'pull', 'unpublish_event', 'publish_without_email', 'remote_org_id', 'name' ,'self_signed', 'cert_file', 'client_cert_file', 'push_rules', 'pull_rules', 'internal', 'skip_proxy');
$fieldList = array('id', 'url', 'push', 'pull', 'caching_enabled', 'unpublish_event', 'publish_without_email', 'remote_org_id', 'name' ,'self_signed', 'cert_file', 'client_cert_file', 'push_rules', 'pull_rules', 'internal', 'skip_proxy');
$this->request->data['Server']['id'] = $id;
if (isset($this->request->data['Server']['authkey']) && "" != $this->request->data['Server']['authkey']) {
$fieldList[] = 'authkey';
@ -1830,4 +1841,43 @@ misp.direct_call(relative_path, body)
}
}
public function cache($id = 'all')
{
if (Configure::read('MISP.background_jobs')) {
$this->loadModel('Job');
$this->Job->create();
$data = array(
'worker' => 'default',
'job_type' => 'cache_servers',
'job_input' => intval($id) ? $id : 'all',
'status' => 0,
'retries' => 0,
'org' => $this->Auth->user('Organisation')['name'],
'message' => __('Starting server caching.'),
);
$this->Job->save($data);
$jobId = $this->Job->id;
$process_id = CakeResque::enqueue(
'default',
'ServerShell',
array('cacheServer', $this->Auth->user('id'), $id, $jobId),
true
);
$this->Job->saveField('process_id', $process_id);
$message = 'Server caching job initiated.';
} else {
$result = $this->Server->cacheServerInitiator($this->Auth->user(), $id);
if (!$result) {
$this->Flash->error(__('Caching the servers has failed.'));
$this->redirect(array('action' => 'index'));
}
$message = __('Caching the servers has successfully completed.');
}
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('Server', 'cache', false, $this->response->type(), $message);
} else {
$this->Flash->info($message);
$this->redirect(array('action' => 'index'));
}
}
}

View File

@ -156,17 +156,42 @@ class TagCollectionsController extends AppController
if ($tag_id === false) {
$tag_id = $this->request->data['tag'];
}
$conditions = array('LOWER(Tag.name) LIKE' => strtolower(trim($tag_id)));
$conditions = array();
if (!$this->_isSiteAdmin()) {
$conditions['Tag.org_id'] = array('0', $this->Auth->user('org_id'));
$conditions['Tag.user_id'] = array('0', $this->Auth->user('id'));
}
if (!is_numeric($tag_id)) {
$tag = $this->TagCollection->Tag->find('first', array('recursive' => -1, 'conditions' => $conditions));
if (empty($tag)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status'=>200, 'type' => 'json'));
$tag_ids = json_decode($tag_id);
$tag_lookups = array();
foreach ($tag_ids as $temp) {
if (is_numeric($temp)) {
$tag_lookups['OR']['Tag.id'][] = $temp;
} else {
$tag_lookups['OR']['LOWER(Tag.name) LIKE'][] = strtolower(trim($tag_id));
}
}
if ($tag_ids !== null && is_array($tag_ids)) { // can decode json
$tag_ids = $this->TagCollection->TagCollectionTag->Tag->find('list', array(
'conditions' => array(
'AND' => array(
$conditions,
$tag_lookups
)
),
'fields' => array('Tag.id', 'Tag.id')
));
$tag_id_list = array_values($tag_ids);
if (empty($tag_id_list)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag(s).')), 'status'=>200, 'type' => 'json'));
}
} else {
$tag = $this->TagCollection->TagCollectionTag->Tag->find('first', array('recursive' => -1, 'conditions' => $conditions));
if (empty($tag)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status'=>200, 'type' => 'json'));
}
$tag_id = $tag['Tag']['id'];
}
$tag_id = $tag['Tag']['id'];
}
$tagCollection = $this->TagCollection->find('first', array(
'recursive' => -1,
@ -176,37 +201,54 @@ class TagCollectionsController extends AppController
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid tag collection.')), 'status'=>200, 'type' => 'json'));
}
if (!$this->_isSiteAdmin()) {
if (!$this->userRole['perm_tagger'] || ($this->Auth->user('org_id') !== $tag_collection['TagCollection']['org_id'])) {
if (!$this->userRole['perm_tagger'] || ($this->Auth->user('org_id') !== $tagCollection['TagCollection']['org_id'])) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')), 'status'=>200, 'type' => 'json'));
}
}
$this->TagCollection->TagCollectionTag->Tag->id = $tag_id;
if (!$this->TagCollection->TagCollectionTag->Tag->exists()) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status'=>200, 'type' => 'json'));
}
$tag = $this->TagCollection->TagCollectionTag->Tag->find('first', array(
'conditions' => array('Tag.id' => $tag_id),
'recursive' => -1,
'fields' => array('Tag.name')
));
$found = $this->TagCollection->TagCollectionTag->find('first', array(
'conditions' => array(
'tag_collection_id' => $id,
'tag_id' => $tag_id
),
'recursive' => -1,
));
$this->autoRender = false;
if (!empty($found)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Tag is already attached to this collection.')), 'status'=>200, 'type' => 'json'));
$error = false;
$success = false;
if (empty($tag_id_list)) {
$tag_id_list = array($tag_id);
}
$this->TagCollection->TagCollectionTag->create();
if ($this->TagCollection->TagCollectionTag->save(array('tag_collection_id' => $id, 'tag_id' => $tag_id))) {
$log = ClassRegistry::init('Log');
$log->createLogEntry($this->Auth->user(), 'tag', 'TagCollection', $id, 'Attached tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" to collection (' . $id . ')', 'Event (' . $id . ') tagged as Tag (' . $tag_id . ')');
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'Tag added.')), 'status'=>200, 'type' => 'json'));
foreach ($tag_id_list as $tag_id) {
$this->TagCollection->TagCollectionTag->Tag->id = $tag_id;
if (!$this->TagCollection->TagCollectionTag->Tag->exists()) {
$error = __('Invalid Tag.');
continue;
}
$tag = $this->TagCollection->TagCollectionTag->Tag->find('first', array(
'conditions' => array('Tag.id' => $tag_id),
'recursive' => -1,
'fields' => array('Tag.name')
));
$found = $this->TagCollection->TagCollectionTag->find('first', array(
'conditions' => array(
'tag_collection_id' => $id,
'tag_id' => $tag_id
),
'recursive' => -1,
));
if (!empty($found)) {
$error = __('Tag is already attached to this event.');
continue;
}
$this->TagCollection->TagCollectionTag->create();
if ($this->TagCollection->TagCollectionTag->save(array('tag_collection_id' => $id, 'tag_id' => $tag_id))) {
$log = ClassRegistry::init('Log');
$log->createLogEntry($this->Auth->user(), 'tag', 'TagCollection', $id, 'Attached tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" to collection (' . $id . ')', 'Event (' . $id . ') tagged as Tag (' . $tag_id . ')');
$success = __('Tag(s) added.');
} else {
$fail = __('Tag(s) could not be added.');
}
}
if ($success) {
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => $success)), 'status'=>200, 'type' => 'json'));
} elseif (empty($fail)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => __('All tags are already present, nothing to add.'), 'check_publish' => true)), 'status'=>200, 'type' => 'json'));
} else {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Tag could not be added.')), 'status'=>200, 'type' => 'json'));
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => $fail)), 'status'=>200, 'type' => 'json'));
}
}

View File

@ -572,20 +572,44 @@ class TagsController extends AppController
if (!$this->_isSiteAdmin() && !$this->userRole['perm_tagger']) {
throw new NotFoundException('You don\'t have permission to do that.');
}
$items = array();
$favourites = $this->Tag->FavouriteTag->find('count', array('conditions' => array('FavouriteTag.user_id' => $this->Auth->user('id'))));
if ($favourites) {
$items[] = array(
'name' => __('Favourite Tags'),
'value' => "/tags/selectTag/" . h($id) . "/favourites/" . h($scope)
);
}
if ($scope !== 'tag_collection') {
$items[] = array(
'name' => __('Tag Collections'),
'value' => "/tags/selectTag/" . h($id) . "/collections/" . h($scope)
);
}
$items[] = array(
'name' => __('All Tags'),
'value' => "/tags/selectTag/" . h($id) . "/all/" . h($scope)
);
$this->loadModel('Taxonomy');
$options = $this->Taxonomy->find('list', array('conditions' => array('enabled' => true), 'fields' => array('namespace'), 'order' => array('Taxonomy.namespace ASC')));
foreach ($options as $k => $option) {
$tags = $this->Taxonomy->getTaxonomyTags($k, false, true);
if (empty($tags)) {
unset($options[$k]);
if (!empty($tags)) {
$items[] = array(
'name' => __('Taxonomy Library') . ":" . h($option),
'value' => "/tags/selectTag/" . h($id) . "/" . h($k) . "/" . h($scope)
);
}
}
$this->set('scope', $scope);
$this->set('object_id', $id);
$this->set('options', $options);
$this->set('favourites', $favourites);
$this->render('ajax/taxonomy_choice');
$this->set('items', $items);
$this->set('options', array( // set chosen (select picker) options
'select_options' => array(
'multiple' => 0,
),
));
$this->render('/Elements/generic_picker');
}
public function selectTag($id, $taxonomy_id, $scope = 'event', $filterData = '')
@ -614,10 +638,11 @@ class TagsController extends AppController
if ($taxonomy_id === 'collections') {
$this->loadModel('TagCollection');
$tagCollections = $this->TagCollection->fetchTagCollection($this->Auth->user());
$options = array();
$tags = array();
$inludedTagListString = array();
$expanded = array();
foreach ($tagCollections as &$tagCollection) {
$options[$tagCollection['TagCollection']['id']] = $tagCollection['TagCollection']['name'];
$tags[$tagCollection['TagCollection']['id']] = $tagCollection['TagCollection'];
$expanded[$tagCollection['TagCollection']['id']] = empty($tagCollection['TagCollection']['description']) ? $tagCollection['TagCollection']['name'] : $tagCollection['TagCollection']['description'];
if (!empty($tagCollection['TagCollectionTag'])) {
$tagList = array();
@ -630,44 +655,49 @@ class TagsController extends AppController
$tagCollection['TagCollectionTag'] = array_values($tagCollection['TagCollectionTag']);
}
$tagList = implode(', ', $tagList);
$inludedTagListString[$tagCollection['TagCollection']['id']] = $tagList;
$expanded[$tagCollection['TagCollection']['id']] .= sprintf(' (%s)', $tagList);
}
}
$this->set('scope', $scope);
$this->set('object_id', $id);
$this->set('options', $options);
$this->set('expanded', $expanded);
$this->set('custom', $taxonomy_id == 0 ? true : false);
$this->set('filterData', $filterData);
$this->render('ajax/select_tag');
} else {
if ($taxonomy_id === '0') {
$options = $this->Taxonomy->getAllTaxonomyTags(true);
$expanded = $options;
$tags = $this->Taxonomy->getAllTaxonomyTags(true);
$expanded = $tags;
} elseif ($taxonomy_id === 'favourites') {
$tags = array();
$conditions = array('FavouriteTag.user_id' => $this->Auth->user('id'));
$tags = $this->Tag->FavouriteTag->find('all', array(
$favTags = $this->Tag->FavouriteTag->find('all', array(
'conditions' => $conditions,
'recursive' => -1,
'contain' => array('Tag.name')
'contain' => array('Tag'),
'order' => array('Tag.name asc')
));
foreach ($tags as $tag) {
$options[$tag['FavouriteTag']['tag_id']] = $tag['Tag']['name'];
$expanded = $options;
foreach ($favTags as $favTag) {
$tags[$favTag['FavouriteTag']['tag_id']] = $favTag['Tag'];
$expanded = $tags;
}
} elseif ($taxonomy_id === 'all') {
$conditions = array('Tag.org_id' => array(0, $this->Auth->user('org_id')));
$conditions = array('Tag.user_id' => array(0, $this->Auth->user('id')));
$conditions['Tag.hide_tag'] = 0;
$options = $this->Tag->find('list', array('fields' => array('Tag.name'), 'conditions' => $conditions));
$expanded = $options;
$allTags = $this->Tag->find('all', array('conditions' => $conditions, 'recursive' => -1, 'order' => array('name asc')));
$allTags = $this->Tag->EventTag->Event->massageTags(array('EventTag' => $allTags), 'Event', false);
$allTags = $allTags['EventTag'];
$tags = array();
foreach ($allTags as $i => $tag) {
if (!empty($tag['Tag'])) {
$tags[$tag['Tag']['id']] = $tag['Tag'];
}
}
unset($allTags);
$expanded = $tags;
} else {
$taxonomies = $this->Taxonomy->getTaxonomy($taxonomy_id);
$options = array();
$tags = array();
if (!empty($taxonomies['entries'])) {
foreach ($taxonomies['entries'] as $entry) {
if (!empty($entry['existing_tag']['Tag'])) {
$options[$entry['existing_tag']['Tag']['id']] = $entry['existing_tag']['Tag']['name'];
$tags[$entry['existing_tag']['Tag']['id']] = $entry['existing_tag']['Tag'];
$expanded[$entry['existing_tag']['Tag']['id']] = $entry['expanded'];
}
}
@ -676,7 +706,7 @@ class TagsController extends AppController
// Unset all tags that this user cannot use for tagging, determined by the org restriction on tags
if (!$this->_isSiteAdmin()) {
foreach ($banned_tags as $banned_tag) {
unset($options[$banned_tag]);
unset($tags[$banned_tag]);
unset($expanded[$banned_tag]);
}
}
@ -685,22 +715,71 @@ class TagsController extends AppController
'fields' => array('Tag.id')
));
foreach ($hidden_tags as $hidden_tag) {
unset($options[$hidden_tag]);
unset($tags[$hidden_tag]);
unset($expanded[$hidden_tag]);
}
$this->set('scope', $scope);
$this->set('object_id', $id);
foreach ($options as $k => $v) {
if (substr($v, 0, strlen('misp-galaxy:')) === 'misp-galaxy:') {
unset($options[$k]);
}
$this->set('scope', $scope);
$this->set('object_id', $id);
App::uses('TextColourHelper', 'View/Helper');
$textColourHelper = new TextColourHelper(new View());
$items = array();
foreach ($tags as $k => $tag) {
$tagTemplate = '<span href="#" class="tagComplete" style="background-color:{{=it.background}}; color:{{=it.color}}">{{=it.name}}</span>';
$tagName = $tag['name'];
$choice_id = $k;
if ($taxonomy_id === 'collections') {
$choice_id = 'collection_' . $choice_id;
}
$onClickForm = 'quickSubmitTagForm';
if ($scope === 'attribute') {
$onClickForm = 'quickSubmitAttributeTagForm';
}
if ($scope === 'tag_collection') {
$onClickForm = 'quickSubmitTagCollectionTagForm';
}
if (is_numeric($taxonomy_id) && $taxonomy_id > 0 && isset($expanded[$tag['id']])) {
if (strlen($expanded[$tag['id']]) < 50) {
$tagTemplate .= '<i style="float:right; font-size: smaller;">{{=it.expanded}}</i>';
} else {
$tagTemplate .= '<it class="fa fa-info-circle" style="float:right;" title="{{=it.expanded}}"></it>';
}
}
$this->set('options', $options);
$this->set('expanded', $expanded);
$this->set('custom', $taxonomy_id == 0 ? true : false);
$this->set('filterData', $filterData);
$this->render('ajax/select_tag');
if ($taxonomy_id === 'collections') {
$tagTemplate .= '<div class="apply_css_arrow" style="padding-left: 5px; margin-top: 5px; font-size: smaller;"><i>{{=it.includes}}</i></div>';
}
$itemParam = array(
'name' => h($tagName),
'value' => h($choice_id),
'additionalData' => array(
'id' => h($id)
),
'template' => $tagTemplate,
'templateData' => array(
'name' => h($tagName),
'background' => h(isset($tag['colour']) ? $tag['colour'] : '#ffffff'),
'color' => h(isset($tag['colour']) ? $textColourHelper->getTextColour($tag['colour']) : '#0088cc'),
'expanded' => h($expanded[$tag['id']])
)
);
if ($taxonomy_id === 'collections') {
$TagCollectionTag = __('Includes: ') . h($inludedTagListString[$tag['id']]);
$itemParam['templateData']['includes'] = $TagCollectionTag;
}
$items[] = $itemParam;
}
$this->set('items', $items);
$this->set('options', array( // set chosen (select picker) options
'functionName' => $onClickForm,
'multiple' => -1,
));
$this->render('ajax/select_tag');
}
public function tagStatistics($percentage = false, $keysort = false)

View File

@ -119,6 +119,7 @@ class TaxonomiesController extends AppController
'recursive' => -1,
'conditions' => array('Taxonomy.id' => $id),
));
$this->Taxonomy->disableTags($id);
$taxonomy['Taxonomy']['enabled'] = 0;
$this->Taxonomy->save($taxonomy);
$this->Log = ClassRegistry::init('Log');

View File

@ -15,12 +15,20 @@ class CacheExport
throw new MethodNotAllowedException('Invalid hashing algo');
}
if ($options['scope'] === 'Attribute') {
return hash($hash_type, $data['Attribute']['value']);
$temp = hash($hash_type, $data['Attribute']['value']);
if (!empty($options['filters']['includeEventUuid'])) {
$temp .= ',' . $data['Event']['uuid'];
}
return $temp;
}
if ($options['scope'] === 'Event') {
$result = array();
foreach ($data['Attribute'] as $attribute) {
$result[] = hash($hash_type, $data['Attribute']['value']);
$temp = hash($hash_type, $data['Attribute']['value']);
if (!empty($options['filters']['includeEventUuid'])) {
$temp .= ',' . $data['Event']['uuid'];
}
$result[] = $temp;
}
return implode($this->separator(), $result);
}

View File

@ -72,7 +72,7 @@ class AppModel extends Model
7 => false, 8 => false, 9 => false, 10 => false, 11 => false, 12 => false,
13 => false, 14 => false, 15 => false, 18 => false, 19 => false, 20 => false,
21 => false, 22 => false, 23 => false, 24 => false, 25 => false, 26 => false,
27 => false
27 => false, 28 => false
);
public function afterSave($created, $options = array())
@ -1086,6 +1086,9 @@ class AppModel extends Model
case 27:
$sqlArray[] = 'ALTER TABLE `tags` CHANGE `org_id` `org_id` int(11) NOT NULL DEFAULT 0;';
break;
case 28:
$sqlArray[] = "ALTER TABLE `servers` ADD `caching_enabled` tinyint(1) NOT NULL DEFAULT 0;";
break;
case 'fixNonEmptySharingGroupID':
$sqlArray[] = 'UPDATE `events` SET `sharing_group_id` = 0 WHERE `distribution` != 4;';
$sqlArray[] = 'UPDATE `attributes` SET `sharing_group_id` = 0 WHERE `distribution` != 4;';

View File

@ -3294,13 +3294,18 @@ class Attribute extends AppModel
public function setTimestampConditions($timestamp, $conditions, $scope = 'Event.timestamp')
{
if (is_array($timestamp)) {
$timestamp[0] = $this->Event->resolveTimeDelta($timestamp[0]);
$timestamp[1] = $this->Event->resolveTimeDelta($timestamp[1]);
$conditions['AND'][] = array($scope . ' >=' => intval($timestamp[0]));
$conditions['AND'][] = array($scope . ' <=' => intval($timestamp[1]));
$timestamp[0] = intval($this->Event->resolveTimeDelta($timestamp[0]));
$timestamp[1] = intval($this->Event->resolveTimeDelta($timestamp[1]));
if ($timestamp[0] > $timestamp[1]) {
$temp = $timestamp[0];
$timestamp[0] = $timestamp[1];
$timestamp[1] = $temp;
}
$conditions['AND'][] = array($scope . ' >=' => $timestamp[0]);
$conditions['AND'][] = array($scope . ' <=' => $timestamp[1]);
} else {
$timestamp = $this->Event->resolveTimeDelta($timestamp);
$conditions['AND'][] = array($scope . ' >=' => intval($timestamp));
$timestamp = intval($this->Event->resolveTimeDelta($timestamp));
$conditions['AND'][] = array($scope . ' >=' => $timestamp);
}
return $conditions;
}

View File

@ -123,4 +123,89 @@ class AttributeTag extends AppModel
}
return array('scores' => $scores, 'maxScore' => $maxScore);
}
// find all tags that belong to a list of attributes (contained in the same event)
public function getAttributesTags($user, $requestedEventId, $attributeIds) {
if (is_array($attributeIds) && empty($attributeIds)) {
throw new NotFoundException(__('Invalid attributes'));
}
$allTags = array();
$attributes = $this->Attribute->fetchAttributes($user, array('conditions' => array('Attribute.id' => $attributeIds, 'Attribute.event_id' => $requestedEventId)));
foreach ($attributes as $attribute) {
$attributeTags = $this->find('all', array(
'conditions' => array(
'attribute_id' => $attribute['Attribute']['id']
),
'contain' => array('Tag.id', 'Tag.colour', 'Tag.name')
));
$this->GalaxyCluster = ClassRegistry::init('GalaxyCluster');
$cluster_names = $this->GalaxyCluster->find('list', array('fields' => array('GalaxyCluster.tag_name'), 'group' => array('GalaxyCluster.tag_name', 'GalaxyCluster.id')));
foreach ($attributeTags as $k => $attributeTag) {
if (in_array($attributeTag['Tag']['name'], $cluster_names)) {
unset($attributeTags[$k]);
}
}
foreach ($attributeTags as $k => $attributeTag) {
$allTags[$attributeTag['Tag']['id']] = $attributeTag['Tag'];
}
}
return $allTags;
}
// find all galaxies that belong to a list of attributes (contains in the same event)
public function getAttributesClusters($user, $requestedEventId, $attributeIds) {
if ($attributeIds === null) {
throw new NotFoundException(__('Invalid attributes'));
}
$allClusters = array();
foreach ($attributeIds as $id) {
$attribute = $this->Attribute->fetchAttributes($user, array('conditions' => array('Attribute.id' => $id)));
if (empty($attribute)) {
throw new MethodNotAllowedException('Invalid attribute.');
}
$eventId = $attribute[0]['Attribute']['event_id'];
if ($eventId != $requestedEventId) { // only takes tags of attributes belonging to the same event
continue;
}
$attributeTags = $this->find('all', array(
'conditions' => array(
'attribute_id' => $id
),
'contain' => array('Tag'),
'fields' => array('Tag.id', 'Tag.colour', 'Tag.name'),
));
$this->GalaxyCluster = ClassRegistry::init('GalaxyCluster');
$cluster_names = $this->GalaxyCluster->find('list', array('fields' => array('GalaxyCluster.tag_name'), 'group' => array('GalaxyCluster.tag_name', 'GalaxyCluster.id')));
foreach ($attributeTags as $k => $attributeTag) {
if (in_array($attributeTag['Tag']['name'], $cluster_names)) {
$cluster = $this->GalaxyCluster->find('first', array(
'conditions' => array('GalaxyCluster.tag_name' => $attributeTag['Tag']['name']),
'fields' => array('value', 'description', 'type'),
'contain' => array(
'GalaxyElement' => array(
'conditions' => array('GalaxyElement.key' => 'synonyms')
)
),
'recursive' => -1
));
// create synonym string
$cluster['GalaxyCluster']['synonyms_string'] = array();
foreach ($cluster['GalaxyElement'] as $element) {
$cluster['GalaxyCluster']['synonyms_string'][] = $element['value'];
}
$cluster['GalaxyCluster']['synonyms_string'] = implode(', ', $cluster['GalaxyCluster']['synonyms_string']);
unset($cluster['GalaxyElement']);
$allClusters[$cluster['GalaxyCluster']['id']] = $cluster['GalaxyCluster'];
}
}
}
return $allClusters;
}
}

View File

@ -1882,6 +1882,15 @@ class Event extends AppModel
}
$event['Attribute'] = $this->Feed->attachFeedCorrelations($event['Attribute'], $user, $event['Event'], $overrideLimit);
}
if (!empty($options['includeServerCorrelations']) && $user['org_id'] == Configure::read('MISP.host_org_id')) {
$this->Feed = ClassRegistry::init('Feed');
if (!empty($options['overrideLimit'])) {
$overrideLimit = true;
} else {
$overrideLimit = false;
}
$event['Attribute'] = $this->Feed->attachFeedCorrelations($event['Attribute'], $user, $event['Event'], $overrideLimit, 'Server');
}
$event = $this->__filterBlockedAttributesByTags($event, $options, $user);
$event['Attribute'] = $this->__attachSharingGroups(!$options['sgReferenceOnly'], $event['Attribute'], $sharingGroupData);
foreach ($event['Attribute'] as $key => $attribute) {
@ -1966,6 +1975,15 @@ class Event extends AppModel
$event['ShadowAttribute'] = $this->Feed->attachFeedCorrelations($event['ShadowAttribute'], $user, $event['Event'], $overrideLimit);
}
}
if (!empty($options['includeServerCorrelations']) && $user['org_id'] == Configure::read('MISP.host_org_id')) {
$this->Feed = ClassRegistry::init('Feed');
if (!empty($options['overrideLimit'])) {
$overrideLimit = true;
} else {
$overrideLimit = false;
}
$event['ShadowAttribute'] = $this->Feed->attachFeedCorrelations($event['ShadowAttribute'], $user, $event['Event'], $overrideLimit, 'Server');
}
$event['Sighting'] = $this->Sighting->attachToEvent($event, $user);
// remove proposals to attributes that we cannot see
// if the shadow attribute wasn't moved within an attribute before, this is the case
@ -2200,7 +2218,23 @@ class Event extends AppModel
{
if (!empty($params['eventid']) && $params['eventid'] !== 'all') {
$params['eventid'] = $this->convert_filters($params['eventid']);
$conditions = $this->generic_add_filter($conditions, $params['eventid'], 'Event.id');
$keys = array(
'uuid' => 'Event.uuid',
'id' => 'Event.id'
);
$id_params = array();
foreach ($params['eventid'] as $operand => $list) {
foreach ($list as $id) {
if ($operand === 'OR') {
$id_params['AND']['OR'][$keys[Validation::uuid($id) ? 'uuid' : 'id']][] = $id;
} else if ($operand === 'AND') {
$id_params['AND']['AND'][$keys[Validation::uuid($id) ? 'uuid' : 'id']][] = $id;
} else {
$id_params['AND']['NOT'][$keys[Validation::uuid($id) ? 'uuid' : 'id']][] = $id;
}
}
}
$conditions['AND'][] = $id_params;
}
return $conditions;
}
@ -2218,10 +2252,10 @@ class Event extends AppModel
{
if (!empty($params['uuid'])) {
$params['uuid'] = $this->convert_filters($params['uuid']);
if (!empty($options['scope']) || $options['scope'] === 'Event') {
if (!empty($options['scope']) && $options['scope'] === 'Event') {
$conditions = $this->generic_add_filter($conditions, $params['uuid'], 'Event.uuid');
}
if (!empty($options['scope']) || $options['scope'] === 'Attribute') {
if (!empty($options['scope']) && $options['scope'] === 'Attribute') {
$conditions = $this->generic_add_filter($conditions, $params['uuid'], 'Attribute.uuid');
}
}
@ -2232,10 +2266,10 @@ class Event extends AppModel
{
if (!empty($params['mixed_id'])) {
$params['mixed_id'] = $this->convert_filters($params['mixed_id']);
if (!empty($options['scope']) || $options['scope'] === 'Event') {
if (!empty($options['scope']) && $options['scope'] === 'Event') {
$conditions = $this->generic_add_filter($conditions, $params['uuid'], 'Event.uuid');
}
if (!empty($options['scope']) || $options['scope'] === 'Attribute') {
if (!empty($options['scope']) && $options['scope'] === 'Attribute') {
$conditions = $this->generic_add_filter($conditions, $params['uuid'], 'Attribute.uuid');
}
}
@ -5295,12 +5329,12 @@ class Event extends AppModel
$cluster = $this->GalaxyCluster->getCluster($dataTag['Tag']['name']);
if ($cluster) {
$found = false;
foreach ($data['Galaxy'] as $k => $galaxy) {
foreach ($data['Galaxy'] as $j => $galaxy) {
if ($galaxy['id'] == $cluster['GalaxyCluster']['Galaxy']['id']) {
$found = true;
$temp = $cluster;
unset($temp['GalaxyCluster']['Galaxy']);
$data['Galaxy'][$k]['GalaxyCluster'][] = $temp['GalaxyCluster'];
$data['Galaxy'][$j]['GalaxyCluster'][] = $temp['GalaxyCluster'];
continue;
}
}

View File

@ -323,21 +323,34 @@ class Feed extends AppModel
return $data;
}
public function attachFeedCorrelations($objects, $user, &$event, $overrideLimit = false)
public function attachFeedCorrelations($objects, $user, &$event, $overrideLimit = false, $scope = 'Feed')
{
$redis = $this->setupRedis();
if ($redis !== false) {
$params = array(
'recursive' => -1,
'fields' => array('id', 'name', 'url', 'provider', 'source_format')
);
if (!$user['Role']['perm_site_admin']) {
$params['conditions'] = array('Feed.lookup_visible' => 1);
if ($scope === 'Feed') {
$params = array(
'recursive' => -1,
'fields' => array('id', 'name', 'url', 'provider', 'source_format')
);
if (!$user['Role']['perm_site_admin']) {
$params['conditions'] = array('Feed.lookup_visible' => 1);
}
$sources = $this->find('all', $params);
} else {
$params = array(
'recursive' => -1,
'fields' => array('id', 'name', 'url', 'caching_enabled')
);
if (!$user['Role']['perm_site_admin']) {
$params['conditions'] = array('Server.caching_enabled' => 1);
}
$this->Server = ClassRegistry::init('Server');
$sources = $this->Server->find('all', $params);
}
$feeds = $this->find('all', $params);
$counter = 0;
$hashTable = array();
$feedList = array();
$sourceList = array();
$pipe = $redis->multi(Redis::PIPELINE);
$objectsWithFeedHits = array();
$hashTable = array();
@ -352,7 +365,7 @@ class Feed extends AppModel
} else {
$hashTable[$k] = md5($object['value']);
}
$redis->sismember('misp:feed_cache:combined', $hashTable[$k]);
$redis->sismember('misp:' . strtolower($scope) . '_cache:combined', $hashTable[$k]);
$objectKeys[] = $k;
}
$results = array();
@ -374,53 +387,53 @@ class Feed extends AppModel
$hitIds[] = $k;
}
}
foreach ($feeds as $k3 => $feed) {
foreach ($sources as $k3 => $source) {
$pipe = $redis->multi(Redis::PIPELINE);
foreach ($hitIds as $k2 => $k) {
$redis->sismember('misp:feed_cache:' . $feed['Feed']['id'], $hashTable[$k]);
$redis->sismember('misp:' . strtolower($scope) . '_cache:' . $source[$scope]['id'], $hashTable[$k]);
}
$feedHits = $pipe->exec();
foreach ($feedHits as $k4 => $hit) {
$sourceHits = $pipe->exec();
foreach ($sourceHits as $k4 => $hit) {
if ($hit) {
if (!isset($event['Feed'][$feeds[$k3]['Feed']['id']]['id'])) {
if (!isset($event['Feed'][$feeds[$k3]['Feed']['id']])) {
$event['Feed'][$feeds[$k3]['Feed']['id']] = array();
if (!isset($event[$scope][$sources[$k3][$scope]['id']]['id'])) {
if (!isset($event[$scope][$sources[$k3][$scope]['id']])) {
$event[$scope][$sources[$k3][$scope]['id']] = array();
}
$event['Feed'][$feeds[$k3]['Feed']['id']] = array_merge($event['Feed'][$feeds[$k3]['Feed']['id']], $feed['Feed']);
$event[$scope][$sources[$k3][$scope]['id']] = array_merge($event[$scope][$sources[$k3][$scope]['id']], $source[$scope]);
}
$objects[$hitIds[$k4]]['Feed'][] = $feed['Feed'];
$objects[$hitIds[$k4]][$scope][] = $source[$scope];
}
}
if ($feed['Feed']['source_format'] == 'misp') {
if ($scope === 'Server' || $source[$scope]['source_format'] == 'misp') {
$pipe = $redis->multi(Redis::PIPELINE);
$eventUuidHitPosition = array();
$i = 0;
foreach ($objects as $k => $object) {
if (isset($object['Feed'])) {
foreach ($object['Feed'] as $currentFeed) {
if ($feed['Feed']['id'] == $currentFeed['id']) {
if (isset($object[$scope])) {
foreach ($object[$scope] as $currentFeed) {
if ($source[$scope]['id'] == $currentFeed['id']) {
$eventUuidHitPosition[$i] = $k;
$i++;
if (in_array($object['type'], $this->Event->Attribute->getCompositeTypes())) {
$value = explode('|', $object['value']);
$redis->smembers('misp:feed_cache:event_uuid_lookup:' . md5($value[0]));
$redis->smembers('misp:' . strtolower($scope) . '_cache:event_uuid_lookup:' . md5($value[0]));
} else {
$redis->smembers('misp:feed_cache:event_uuid_lookup:' . md5($object['value']));
$redis->smembers('misp:' . strtolower($scope) . '_cache:event_uuid_lookup:' . md5($object['value']));
}
}
}
}
}
$mispFeedHits = $pipe->exec();
foreach ($mispFeedHits as $feedhitPos => $f) {
foreach ($mispFeedHits as $sourcehitPos => $f) {
foreach ($f as $url) {
$urlParts = explode('/', $url);
if (empty($event['Feed'][$urlParts[0]]['event_uuids']) || !in_array($urlParts[1], $event['Feed'][$urlParts[0]]['event_uuids'])) {
$event['Feed'][$urlParts[0]]['event_uuids'][] = $urlParts[1];
if (empty($event[$scope][$urlParts[0]]['event_uuids']) || !in_array($urlParts[1], $event[$scope][$urlParts[0]]['event_uuids'])) {
$event[$scope][$urlParts[0]]['event_uuids'][] = $urlParts[1];
}
foreach ($objects[$eventUuidHitPosition[$feedhitPos]]['Feed'] as $tempKey => $tempFeed) {
foreach ($objects[$eventUuidHitPosition[$sourcehitPos]][$scope] as $tempKey => $tempFeed) {
if ($tempFeed['id'] == $urlParts[0]) {
$objects[$eventUuidHitPosition[$feedhitPos]]['Feed'][$tempKey]['event_uuids'][] = $urlParts[1];
$objects[$eventUuidHitPosition[$sourcehitPos]][$scope][$tempKey]['event_uuids'][] = $urlParts[1];
}
}
}
@ -429,8 +442,8 @@ class Feed extends AppModel
}
}
}
if (!empty($event['Feed'])) {
$event['Feed'] = array_values($event['Feed']);
if (!empty($event[$scope])) {
$event[$scope] = array_values($event[$scope]);
}
return $objects;
}
@ -1241,6 +1254,25 @@ class Feed extends AppModel
$feeds[$k]['Feed']['values'] = $redis->sCard('misp:feed_cache:' . $feed['Feed']['id']);
}
$feeds = array_values($feeds);
$this->Server = ClassRegistry::init('Server');
$servers = $this->Server->find('all', array(
'recursive' => -1,
'fields' => array('id', 'url', 'name'),
'contain' => array('RemoteOrg' => array('fields' => array('RemoteOrg.id', 'RemoteOrg.name'))),
'conditions' => array('Server.caching_enabled')
));
foreach ($servers as $k => $server) {
if (!$redis->exists('misp:server_cache:' . $server['Server']['id'])) {
unset($servers[$k]);
continue;
}
$servers[$k]['Server']['input_source'] = 'network';
$servers[$k]['Server']['source_format'] = 'misp';
$servers[$k]['Server']['provider'] = $servers[$k]['RemoteOrg']['name'];
$servers[$k]['Server']['default'] = false;
$servers[$k]['Server']['is_misp_server'] = true;
$servers[$k]['Server']['values'] = $redis->sCard('misp:server_cache:' . $server['Server']['id']);
}
foreach ($feeds as $k => $feed) {
foreach ($feeds as $k2 => $feed2) {
if ($k == $k2) {
@ -1252,6 +1284,37 @@ class Feed extends AppModel
'overlap_percentage' => round(100 * count($intersect) / $feeds[$k]['Feed']['values']),
));
}
foreach ($servers as $k2 => $server) {
$intersect = $redis->sInter('misp:feed_cache:' . $feed['Feed']['id'], 'misp:server_cache:' . $server['Server']['id']);
$feeds[$k]['Feed']['ComparedFeed'][] = array_merge(array_intersect_key($server['Server'], $fields), array(
'overlap_count' => count($intersect),
'overlap_percentage' => round(100 * count($intersect) / $feeds[$k]['Feed']['values']),
));
}
}
foreach ($servers as $k => $server) {
foreach ($feeds as $k2 => $feed2) {
$intersect = $redis->sInter('misp:server_cache:' . $server['Server']['id'], 'misp:feed_cache:' . $feed2['Feed']['id']);
$servers[$k]['Server']['ComparedFeed'][] = array_merge(array_intersect_key($feed2['Feed'], $fields), array(
'overlap_count' => count($intersect),
'overlap_percentage' => round(100 * count($intersect) / $servers[$k]['Server']['values']),
));
}
foreach ($servers as $k2 => $server2) {
if ($k == $k2) {
continue;
}
$intersect = $redis->sInter('misp:server_cache:' . $server['Server']['id'], 'misp:server_cache:' . $server2['Server']['id']);
$servers[$k]['Server']['ComparedFeed'][] = array_merge(array_intersect_key($server2['Server'], $fields), array(
'overlap_count' => count($intersect),
'overlap_percentage' => round(100 * count($intersect) / $servers[$k]['Server']['values']),
));
}
}
foreach ($servers as $k => $server) {
$server['Feed'] = $server['Server'];
unset($server['Server']);
$feeds[] = $server;
}
return $feeds;
}

View File

@ -243,6 +243,116 @@ class Galaxy extends AppModel
return 'Could not attach the cluster';
}
public function detachCluster($user, $target_type, $target_id, $cluster_id) {
$cluster = $this->GalaxyCluster->find('first', array(
'recursive' => -1,
'conditions' => array('id' => $cluster_id),
'fields' => array('tag_name', 'id', 'value')
));
$this->Tag = ClassRegistry::init('Tag');
if ($target_type === 'event') {
$target = $this->Tag->EventTag->Event->fetchEvent($user, array('eventid' => $target_id, 'metadata' => 1));
if (empty($target)) {
throw new NotFoundException(__('Invalid %s.', $target_type));
}
$target = $target[0];
$event = $target;
$event_id = $target['Event']['id'];
$org_id = $event['Event']['org_id'];
$orgc_id = $event['Event']['orgc_id'];
} elseif ($target_type === 'attribute') {
$target = $this->Tag->AttributeTag->Attribute->fetchAttributes($user, array('conditions' => array('Attribute.id' => $target_id), 'flatten' => 1));
if (empty($target)) {
throw new NotFoundException(__('Invalid %s.', $target_type));
}
$target = $target[0];
$event_id = $target['Attribute']['event_id'];
$event = $this->Tag->EventTag->Event->fetchEvent($user, array('eventid' => $event_id, 'metadata' => 1));
if (empty($event)) {
throw new NotFoundException(__('Invalid event'));
}
$event = $event[0];
$org_id = $event['Event']['org_id'];
$orgc_id = $event['Event']['org_id'];
} elseif ($target_type === 'tag_collection') {
$target = $this->Tag->TagCollectionTag->TagCollection->fetchTagCollection($user, array('conditions' => array('TagCollection.id' => $target_id)));
if (empty($target)) {
throw new NotFoundException(__('Invalid %s.', $target_type));
}
$target = $target[0];
$org_id = $target['org_id'];
$orgc_id = $org_id;
}
if (!$user['Role']['perm_site_admin'] && !$user['Role']['perm_sync']) {
if (
($scope === 'tag_collection' && !$user['Role']['perm_tag_editor']) ||
($scope !== 'tag_collection' && !$user['Role']['perm_tagger']) ||
($user['org_id'] !== $org_id && $user['org_id'] !== $orgc_id)
) {
throw new MethodNotAllowedException('Invalid ' . Inflector::humanize($targe_type) . '.');
}
}
$tag_id = $this->Tag->captureTag(array('name' => $cluster['GalaxyCluster']['tag_name'], 'colour' => '#0088cc', 'exportable' => 1), $user);
if ($target_type == 'attribute') {
$existingTargetTag = $this->Tag->AttributeTag->find('first', array(
'conditions' => array('AttributeTag.tag_id' => $tag_id, 'AttributeTag.attribute_id' => $target_id),
'recursive' => -1,
'contain' => array('Tag')
));
} elseif ($target_type == 'event') {
$existingTargetTag = $this->Tag->EventTag->find('first', array(
'conditions' => array('EventTag.tag_id' => $tag_id, 'EventTag.event_id' => $target_id),
'recursive' => -1,
'contain' => array('Tag')
));
} elseif ($target_type == 'tag_collection') {
$existingTargetTag = $this->Tag->TagCollectionTag->TagCollection->find('first', array(
'conditions' => array('tag_id' => $tag_id, 'tag_collection_id' => $target_id),
'recursive' => -1,
'contain' => array('Tag')
));
}
if (empty($existingTargetTag)) {
return 'Cluster not attached.';
} else {
if ($target_type == 'event') {
$result = $this->Tag->EventTag->delete($existingTargetTag['EventTag']['id']);
} elseif ($target_type == 'attribute') {
$result = $this->Tag->AttributeTag->delete($existingTargetTag['AttributeTag']['id']);
} elseif ($target_type == 'tag_collection') {
$result = $this->Tag->TagCollectionTag->delete($existingTargetTag['TagCollectionTag']['id']);
}
if ($result) {
if ($target_type !== 'tag_collection') {
$this->Tag->EventTag->Event->insertLock($user, $event['Event']['id']);
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Tag->EventTag->Event->save($event);
}
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$this->Log->save(array(
'org' => $user['Organisation']['name'],
'model' => ucfirst($target_type),
'model_id' => $target_id,
'email' => $user['email'],
'action' => 'galaxy',
'title' => 'Detached ' . $cluster['GalaxyCluster']['value'] . ' (' . $cluster['GalaxyCluster']['id'] . ') to ' . $target_type . ' (' . $target_id . ')',
'change' => ''
));
return 'Cluster detached';
} else {
return 'Could not detach cluster';
}
}
}
public function getMitreAttackGalaxyId($type="mitre-enterprise-attack-attack-pattern")
{
$galaxy = $this->find('first', array(

View File

@ -4247,4 +4247,106 @@ class Server extends AppModel
}
return true;
}
public function cacheServerInitiator($user, $id = 'all', $jobId = false)
{
$params = array(
'conditions' => array('caching_enabled' => 1),
'recursive' => -1
);
$redis = $this->setupRedis();
if ($redis === false) {
return 'Redis not reachable.';
}
if ($id !== 'all') {
$params['conditions']['Server.id'] = $id;
} else {
$redis->del('misp:server_cache:combined');
$redis->del('misp:server_cache:event_uuid_lookup:');
}
$servers = $this->find('all', $params);
if ($jobId) {
$job = ClassRegistry::init('Job');
$job->id = $jobId;
if (!$job->exists()) {
$jobId = false;
}
}
foreach ($servers as $k => $server) {
$this->__cacheInstance($server, $redis, $jobId);
if ($jobId) {
$job->saveField('progress', 100 * $k / count($servers));
$job->saveField('message', 'Server ' . $server['Server']['id'] . ' cached.');
}
}
return true;
}
private function __cacheInstance($server, $redis, $jobId = false)
{
$continue = true;
$i = 0;
if ($jobId) {
$job = ClassRegistry::init('Job');
$job->id = $jobId;
}
$redis->del('misp:server_cache:' . $server['Server']['id']);
$HttpSocket = null;
$HttpSocket = $this->setupHttpSocket($server, $HttpSocket);
while ($continue) {
$i++;
$pipe = $redis->multi(Redis::PIPELINE);
$chunk_size = 50000;
$data = $this->__getCachedAttributes($server, $HttpSocket, $chunk_size, $i);
if (empty(trim($data))) {
$continue = false;
} else {
$data = explode(PHP_EOL, trim($data));
foreach ($data as $entry) {
list($value, $uuid) = explode(',', $entry);
if (!empty($value)) {
$redis->sAdd('misp:server_cache:' . $server['Server']['id'], $value);
$redis->sAdd('misp:server_cache:combined', $value);
$redis->sAdd('misp:server_cache:event_uuid_lookup:' . $value, $server['Server']['id'] . '/' . $uuid);
}
}
}
if ($jobId) {
$job->saveField('message', 'Server ' . $server['Server']['id'] . ': ' . ((($i -1) * $chunk_size) + count($data)) . ' attributes cached.');
}
$pipe->exec();
}
$redis->set('misp:server_cache_timestamp:' . $server['Server']['id'], time());
return true;
}
private function __getCachedAttributes($server, $HttpSocket, $chunk_size, $i)
{
$filter_rules = array(
'returnFormat' => 'cache',
'includeEventUuid' => 1,
'page' => $i,
'limit' => $chunk_size
);
debug($filter_rules);
$request = $this->setupSyncRequest($server);
try {
$response = $HttpSocket->post($server['Server']['url'] . '/attributes/restSearch.json', json_encode($filter_rules), $request);
} catch (SocketException $e) {
return $e->getMessage();
}
return $response->body;
}
public function attachServerCacheTimestamps($data)
{
$redis = $this->setupRedis();
if ($redis === false) {
return $data;
}
foreach ($data as $k => $v) {
$data[$k]['Server']['cache_timestamp'] = $redis->get('misp:server_cache_timestamp:' . $data[$k]['Server']['id']);
}
return $data;
}
}

View File

@ -78,6 +78,10 @@
echo $this->Form->input('batch_import', array(
'type' => 'checkbox'
));
echo '<div class="input clear"></div>';
echo $this->Form->input('disable_correlation', array(
'type' => 'checkbox'
));
?>
</div>
</fieldset>

View File

@ -48,14 +48,36 @@
));
?>
<div class="input clear"></div>
<div class="input clear" data-target="pickerContainerTagRemove">
<label><span class="fa fa-times-circle" style="margin-right: 5px;"></span><?php echo __('Tags to <b>remove</b>') ?></label>
<?php echo $this->Form->input('tags_ids_remove', array('style' => 'display:none;', 'label' => false)); ?>
<?php echo $this->element('generic_picker', array('items' => $tagItemsRemove)); ?>
</div>
<div class="input clear" style="margin-top: 20px;" data-target="pickerContainerTagAdd">
<label><span class="fa fa-plus-circle" style="margin-right: 5px;"></span><?php echo __('Tags to <b>add</b>') ?></label>
<?php echo $this->Form->input('tags_ids_add', array('style' => 'display:none;', 'label' => false)); ?>
<?php echo $this->element('generic_picker', array('items' => $tagItemsAdd)); ?>
</div>
<div class="input clear" style="margin-top: 20px;" data-target="pickerContainerClusterRemove">
<label><span class="fa fa-times-circle" style="margin-right: 5px;"></span><?php echo __('Clusters to <b>remove</b>') ?></label>
<?php echo $this->Form->input('clusters_ids_remove', array('style' => 'display:none;', 'label' => false)); ?>
<?php echo $this->element('generic_picker', array('items' => $clusterItemsRemove)); ?>
</div>
<div class="input clear" style="margin-top: 20px;" data-target="pickerContainerClusterAdd">
<label><span class="fa fa-plus-circle" style="margin-right: 5px;"></span><?php echo __('Clusters to <b>add</b>') ?></label>
<?php echo $this->Form->input('clusters_ids_add', array('style' => 'display:none;', 'label' => false)); ?>
<?php echo $this->element('generic_picker', array('items' => $clusterItemsAdd)); ?>
</div>
</div>
</fieldset>
<p style="color:red;font-weight:bold;display:none;" id="warning-message"><?php echo __('Warning: You are about to share data that is of a classified nature (Attribution / targeting data). Make sure that you are authorised to share this.'); ?></p>
<div class="overlay_spacing">
<div class="overlay_spacing" style="margin-top: 20px;">
<table>
<tr>
<td style="vertical-align:top">
<span id="submitButton" class="btn btn-primary" title="<?php echo __('Submit'); ?>" role="button" tabindex="0" aria-label="<?php echo __('Submit'); ?>" onClick="submitPopoverForm('<?php echo $id;?>', 'massEdit')"><?php echo __('Submit'); ?></span>
<span id="submitButton" class="btn btn-primary" title="<?php echo __('Submit'); ?>" role="button" tabindex="0" aria-label="<?php echo __('Submit'); ?>" onClick="syncMassEditFormAndSubmit(this)"><?php echo __('Submit'); ?></span>
</td>
<td style="width:540px;">&nbsp;</td>
<td style="vertical-align:top;">
@ -82,6 +104,35 @@ foreach ($distributionDescriptions as $type => $def) {
echo "formInfoValues['" . addslashes($type) . "'] = \"" . addslashes($info) . "\";\n"; // as we output JS code we need to add slashes
}
?>
function syncMassEditFormAndSubmit(btn) {
// tag remove
var $form = $(btn).closest('form');
var $input = $form.find('#AttributeTagsIdsRemove');
var $select = $form.find('div[data-target="pickerContainerTagRemove"] select');
var val = $select.val();
val = val !== null && val !== "" && val !== undefined ? val : [];
$input.val(JSON.stringify(val));
// tag add
$input = $form.find('#AttributeTagsIdsAdd');
$select = $form.find('div[data-target="pickerContainerTagAdd"] select');
val = $select.val();
val = val !== null && val !== "" && val !== undefined ? val : [];
$input.val(JSON.stringify(val));
// cluster remove
$input = $form.find('#AttributeClustersIdsRemove');
$select = $form.find('div[data-target="pickerContainerClusterRemove"] select');
val = $select.val();
val = val !== null && val !== "" && val !== undefined ? val : [];
$input.val(JSON.stringify(val));
// cluster add
$input = $form.find('#AttributeClustersIdsAdd');
$select = $form.find('div[data-target="pickerContainerClusterAdd"] select');
val = $select.val();
val = val !== null && val !== "" && val !== undefined ? val : [];
$input.val(JSON.stringify(val));
submitPopoverForm('<?php echo $id;?>', 'massEdit');
}
$(document).ready(function() {

View File

@ -59,6 +59,10 @@
'type' => 'checkbox',
));
}
echo '<div class="input clear"></div>';
echo $this->Form->input('disable_correlation', array(
'type' => 'checkbox'
));
?>
</fieldset>
<p style="color:red;font-weight:bold;display:none;<?php if (isset($ajax) && $ajax) echo "text-align:center;";?> " id="warning-message"><?php echo __('Warning: You are about to share data that is of a sensitive nature (Attribution / targeting data). Make sure that you are authorised to share this.'); ?></p>

View File

@ -208,53 +208,99 @@
<td class="shortish">
<ul class="inline" style="margin:0px;">
<?php
if (!empty($object['Feed'])):
foreach ($object['Feed'] as $feed):
$popover = '';
foreach ($feed as $k => $v):
if ($k == 'id') continue;
if (is_array($v)) {
foreach ($v as $k2 => $v2) {
$v[$k2] = h($v2);
}
$v = implode('<br />', $v);
} else {
$v = h($v);
if (!empty($object['Feed'])) {
foreach ($object['Feed'] as $feed) {
$popover = '';
foreach ($feed as $k => $v) {
if ($k == 'id') continue;
if (is_array($v)) {
foreach ($v as $k2 => $v2) {
$v[$k2] = h($v2);
}
$v = implode('<br />', $v);
} else {
$v = h($v);
}
$popover .= '<span class=\'bold black\'>' . Inflector::humanize(h($k)) . '</span>: <span class="blue">' . $v . '</span><br />';
}
$liContents = '';
if ($isSiteAdmin) {
if ($feed['source_format'] == 'misp') {
$liContents .= sprintf(
'<form action="%s/feeds/previewIndex/1" method="post" style="margin:0px;line-height:auto;">%s%s</form>',
$baseurl,
sprintf(
'<input type="hidden" name="data[Feed][eventid]" value="%s">',
h(json_encode($feed['event_uuids'], true))
),
sprintf(
'<input type="submit" class="linkButton useCursorPointer" value="%s" data-toggle="popover" data-content="%s" data-trigger="hover" style="margin-right:3px;line-height:normal;vertical-align: text-top;" />',
h($feed['id']),
h($popover)
)
);
} else {
$liContents .= sprintf(
'<form>%s</form>',
sprintf(
'<a href="%s/feeds/previewIndex/%s" style="margin-right:3px;">%s</a>',
$baseurl,
h($feed['id']),
h($feed['id'])
)
);
}
} else {
$liContents .= sprintf(
'<span style="margin-right:3px;">%s</span>',
h($feed['id'])
);
}
echo sprintf(
'<li style="padding-right: 0px; padding-left:0px;">%s</li>',
$liContents
);
}
$popover .= '<span class=\'bold black\'>' . Inflector::humanize(h($k)) . '</span>: <span class="blue">' . $v . '</span><br />';
endforeach;
?>
<li style="padding-right: 0px; padding-left:0px;"><span>
<?php
if ($isSiteAdmin):
if ($feed['source_format'] == 'misp'):
?>
<form action="<?php echo $baseurl; ?>/feeds/previewIndex/1" method="post" style="margin:0px;line-height:auto;">
<input type="hidden" name="data[Feed][eventid]" value="<?php echo h(json_encode($feed['event_uuids'], true)); ?>">
<input type="submit" class="linkButton useCursorPointer" value="<?php echo h($feed['id']); ?>" data-toggle="popover" data-content="<?php echo h($popover);?>" data-trigger="hover" style="margin-right:3px;line-height:normal;vertical-align: text-top;" />
</form>
<?php
else:
?>
<form>
<a href="<?php echo $baseurl; ?>/feeds/previewIndex/<?php echo h($feed['id']); ?>" style="margin-right:3px;"><?php echo h($feed['id']); ?></a>
</form>
<?php
endif;
else:
?>
<span style="margin-right:3px;"><?php echo h($feed['id']);?></span>
<?php
endif;
endforeach;
?>
</li>
<?php
elseif (!empty($object['FeedHit'])):
?>
<span class="icon-ok"></span>
<?php
endif;
}
if (!empty($object['Server'])) {
foreach ($object['Server'] as $server) {
$popover = '';
foreach ($server as $k => $v) {
if ($k == 'id') continue;
if (is_array($v)) {
foreach ($v as $k2 => $v2) {
$v[$k2] = h($v2);
}
$v = implode('<br />', $v);
} else {
$v = h($v);
}
$popover .= '<span class=\'bold black\'>' . Inflector::humanize(h($k)) . '</span>: <span class="blue">' . $v . '</span><br />';
}
foreach ($server['event_uuids'] as $k => $event_uuid) {
$liContents = '';
if ($isSiteAdmin) {
$liContents .= sprintf(
'<a href="%s/servers/previewEvent/%s/%s" data-toggle="popover" data-content="%s" data-trigger="hover">%s</a>&nbsp;',
$baseurl,
h($server['id']),
h($event_uuid),
h($popover),
'S' . h($server['id']) . ':' . ($k + 1)
);
} else {
$liContents .= sprintf(
'<span style="margin-right:3px;">%s</span>',
'S' . h($server['id']) . ':' . ($k + 1)
);
}
echo sprintf(
'<li style="padding-right: 0px; padding-left:0px;">%s</li>',
$liContents
);
}
}
}
?>
</ul>
</td>

View File

@ -20,12 +20,12 @@
<?php
else:
?>
<a href="<?php echo $baseurl;?>/attributes/search/attributetag:<?php echo h($tag['Tag']['id']); ?>" class="<?php echo $tagClass; ?>" style="display:inline-block; background-color:<?php echo h($tag['Tag']['colour']);?>;color:<?php echo $this->TextColour->getTextColour($tag['Tag']['colour']);?>"><?php echo h($tag['Tag']['name']); ?></a>
<a href="<?php echo $baseurl;?>/attributes/search/tags:<?php echo h($tag['Tag']['id']); ?>" class="<?php echo $tagClass; ?>" style="display:inline-block; 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;
if ($full):
?>
<div class="tagSecondHalf useCursorPointer noPrint" title="<?php echo __('Remove tag');?>" role="button" tabindex="0" aria-label="<?php echo __('Remove tag');?>" onClick="removeObjectTagPopup('attribute', '<?php echo h($attributeId); ?>', '<?php echo h($tag['Tag']['id']); ?>');">x</div>
<div class="tagSecondHalf useCursorPointer noPrint" title="<?php echo __('Remove tag');?>" role="button" tabindex="0" aria-label="<?php echo __('Remove tag');?>" onClick="removeObjectTagPopup(this, 'attribute', '<?php echo h($attributeId); ?>', '<?php echo h($tag['Tag']['id']); ?>');">x</div>
<?php
endif;
?>
@ -38,7 +38,8 @@
$addTagButton = '&nbsp;';
if ($full) {
$addTagButton = sprintf(
'<button id="addTagButton" class="btn btn-inverse noPrint" style="line-height:10px; padding: 4px 4px;" onClick="getPopup(%s);">+</button>',
'<button id="addTagButton" class="btn btn-inverse noPrint" style="line-height:10px; padding: 4px 4px;" title="%s" onClick="popoverPopup(this, %s);">+</button>',
__("Add tag"),
sprintf("'%s/attribute', 'tags', 'selectTaxonomy'", h($attributeId))
);
}

View File

@ -13,7 +13,7 @@
<?php
if ($full):
?>
<div class="tagSecondHalf useCursorPointer noPrint" title="<?php echo __('Remove tag');?>" role="button" tabindex="0" aria-label="<?php echo __('Remove tag');?>" onClick="removeObjectTagPopup('tag_collection', '<?php echo h($tagCollection['TagCollection']['id']); ?>', '<?php echo h($tag['Tag']['id']); ?>');">x</div>
<div class="tagSecondHalf useCursorPointer noPrint" title="<?php echo __('Remove tag');?>" role="button" tabindex="0" aria-label="<?php echo __('Remove tag');?>" onClick="removeObjectTagPopup(this, 'tag_collection', '<?php echo h($tagCollection['TagCollection']['id']); ?>', '<?php echo h($tag['Tag']['id']); ?>');">x</div>
<?php
endif;
?>
@ -26,7 +26,7 @@
$addTagButton = '&nbsp;';
if ($full) {
$addTagButton = sprintf(
'<button id="addTagButton" class="btn btn-inverse noPrint" style="line-height:10px; padding: 4px 4px;" onClick="getPopup(%s);">+</button>',
'<button id="addTagButton" class="btn btn-inverse noPrint" style="line-height:10px; padding: 4px 4px;" onClick="popoverPopup(this, %s);">+</button>',
sprintf("'%s/tag_collection', 'tags', 'selectTaxonomy'", h($tagCollection['TagCollection']['id']))
);
}

View File

@ -15,7 +15,7 @@
$spanRole = "button";
$spanTabIndex = "0";
$spanAriaLabel = __('Remove tag %s', h($tag['Tag']['name']));
$spanOnClick = "removeObjectTagPopup('event', '" . h($event['Event']['id']) . "', '" . h($tag['Tag']['id']) . "')";
$spanOnClick = "removeObjectTagPopup(this, 'event', '" . h($event['Event']['id']) . "', '" . h($tag['Tag']['id']) . "')";
$span2 = sprintf('<span class="%s" title="%s" role="%s" tabindex="%s" aria-label="%s" onClick="%s">x</span>', $spanClass, $spanTitle, $spanRole, $spanTabIndex, $spanAriaLabel, $spanOnClick);
}
$tagData .= '<span style="white-space:nowrap;">' . $span1 . $span2 . '</span> ';
@ -30,7 +30,7 @@
__('Add a tag'),
'btn btn-inverse noPrint',
'line-height:10px; padding: 4px 4px;',
'getPopup(\'' . h($event['Event']['id']) . '\', \'tags\', \'selectTaxonomy\');'
'popoverPopup(this, \'' . h($event['Event']['id']) . '\', \'tags\', \'selectTaxonomy\');'
);
$buttonData = vsprintf('<button id="%s" title="%s" role ="%s" tabindex="%s" aria-label="%s" class="%s" style="%s" onClick="%s">+</button>', $buttonVars);
}

View File

@ -116,7 +116,8 @@
<div class="tabMenu tabMenuEditBlock noPrint">
<span id="create-button" title="<?php echo __('Add attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Add attribute');?>" class="icon-plus useCursorPointer" onClick="clickCreateButton(<?php echo $event['Event']['id']; ?>, '<?php echo $possibleAction; ?>');"></span>
<span id="multi-edit-button" title="<?php echo __('Edit selected Attributes');?>" role="button" tabindex="0" aria-label="<?php echo __('Edit selected Attributes');?>" class="hidden icon-edit mass-select useCursorPointer" onClick="editSelectedAttributes(<?php echo $event['Event']['id']; ?>);"></span>
<span id="multi-tag-button" title="<?php echo __('Tag selected Attributes');?>" role="button" tabindex="0" aria-label="<?php echo __('Tag selected Attributes');?>" class="hidden icon-tag mass-select useCursorPointer" onClick="getPopup('selected/attribute', 'tags', 'selectTaxonomy');"></span>
<span id="multi-tag-button" title="<?php echo __('Tag selected Attributes');?>" role="button" tabindex="0" aria-label="<?php echo __('Tag selected Attributes');?>" class="hidden icon-tag mass-select useCursorPointer" onClick="popoverPopup(this, 'selected/attribute', 'tags', 'selectTaxonomy');"></span>
<span id="multi-galaxy-button" title="<?php echo __('Add new cluster to selected Attributes');?>" role="button" tabindex="0" aria-label="<?php echo __('Add new cluster to selected Attributes');?>" class="hidden icon-rebel fa-rebel mass-select useCursorPointer" style="font: normal normal normal 14px/1 FontAwesome; vertical-align: top;" onClick="popoverPopup(this, 'selected/attribute', 'galaxies', 'selectGalaxyNamespace');"></span>
<span id="multi-delete-button" title="<?php echo __('Delete selected Attributes');?>" role="button" tabindex="0" aria-label="<?php echo __('Delete selected Attributes');?>" class="hidden icon-trash mass-select useCursorPointer" onClick="multiSelectAction(<?php echo $event['Event']['id']; ?>, 'deleteAttributes');"></span>
<span id="multi-accept-button" title="<?php echo __('Accept selected Proposals');?>" role="button" tabindex="0" aria-label="<?php echo __('Accept selected Proposals');?>" class="hidden icon-ok mass-proposal-select useCursorPointer" onClick="multiSelectAction(<?php echo $event['Event']['id']; ?>, 'acceptProposals');"></span>
<span id="multi-discard-button" title="<?php echo __('Discard selected Proposals');?>" role="button" tabindex="0" aria-label="<?php echo __('Discard selected Proposals');?>" class="hidden icon-remove mass-proposal-select useCursorPointer" onClick="multiSelectAction(<?php echo $event['Event']['id']; ?>, 'discardProposals');"></span>

View File

@ -140,8 +140,8 @@
<div class="input clear">
<button type="button" title="<?php echo __('Insert a quote - just paste your quote between the [quote][/quote] tags.');?>" class="toggle-left btn btn-inverse qet" id = "quote" onclick="insertQuote()"><?php echo __('Quote');?></button>
<button type="button" title="<?php echo __('Insert a link to an event - just enter the event ID between the [event][/event] tags.');?>" class="toggle btn btn-inverse qet" id = "event" onclick="insertEvent()"><?php echo __('Event');?></button>
<button type="button" title="<?php echo __('Insert a link to a discussion thread - enter the thread\'s ID between the [thread][/thread] tags.');?>" class="toggle-right btn btn-inverse qet" id = "thread" onclick="insertThread()"><?php echo __('Thread');?></button>
<button type="button" title="<?php echo __('Insert a link [link][/link] tags.');?>" class="toggle-right btn btn-inverse qet" id = "link" onclick="insertLink()"><?php echo __('Link');?></button>
<button type="button" title="<?php echo __('Insert a link to a discussion thread - enter the thread\'s ID between the [thread][/thread] tags.');?>" class="toggle btn btn-inverse qet" id = "thread" onclick="insertThread()"><?php echo __('Thread');?></button>
<button type="button" title="<?php echo __('Insert a link [link][/link] tags.');?>" class="toggle btn btn-inverse qet" id = "link" onclick="insertLink()"><?php echo __('Link');?></button>
<button type="button" title="<?php echo __('Insert a code [code][/code] tags.');?>" class="toggle-right btn btn-inverse qet" id = "code" onclick="insertCode()"><?php echo __('Code');?></button>
</div>
<?php

View File

@ -20,11 +20,9 @@
<a href="<?php echo $baseurl; ?>/events/index/searchtag:<?php echo h($cluster['tag_id']); ?>" class="icon-th-list" title="<?php echo __('View all events containing this cluster.');?>"></a>
<?php
if ($isSiteAdmin || ($mayModify && $isAclTagger)) {
echo $this->Form->postLink('',
$baseurl . '/galaxy_clusters/detach/' . ucfirst(h($target_id)) . '/' . h($target_type) . '/' . $cluster['tag_id'],
array('class' => 'icon-trash', 'title' => __('Delete'), 'div' => false),
__('Are you sure you want to detach %s from this event?', h($cluster['value']))
);
echo $this->Form->create(false, array('url' => $baseurl . '/galaxy_clusters/detach/' . ucfirst(h($target_id)) . '/' . h($target_type) . '/' . $cluster['tag_id'], 'style' => 'display: inline-block; margin: 0px;'));
echo '<it href="#" class="icon-trash useCursorPointer" title="' . __('Are you sure you want to detach %s from this event?', h($cluster['value'])) . '" onclick="popoverConfirm(this)"></it>';
echo $this->Form->end();
}
?>
<div style="margin-left:15px;display:none;" class="blue galaxy_data">

View File

@ -70,11 +70,9 @@
<a href="<?php echo $baseurl; ?>/events/index/searchtag:<?php echo h($cluster['tag_id']); ?>" class="icon-th-list" title="<?php echo __('View all events containing this cluster.');?>"></a>
<?php
if ($isSiteAdmin || ($mayModify && $isAclTagger)) {
echo $this->Form->postLink('',
$baseurl . '/galaxy_clusters/detach/' . ucfirst(h($target_id)) . '/' . h($target_type) . '/' . $cluster['tag_id'],
array('class' => 'icon-trash', 'title' => 'Delete'),
__('Are you sure you want to detach %s from this %s?', h($cluster['value']), h($target_type))
);
echo $this->Form->create(false, array('url' => $baseurl . '/galaxy_clusters/detach/' . ucfirst(h($target_id)) . '/' . h($target_type) . '/' . h($cluster['tag_id']), 'style' => 'display: inline-block; margin: 0px;'));
echo '<span href="#" class="icon-trash useCursorPointer" title="' . __('Are you sure you want to detach %s from this %s?', h($cluster['value']), h($target_type)) . '" onclick="popoverConfirm(this)"></span>';
echo $this->Form->end();
}
?>
</div>
@ -88,7 +86,7 @@
<?php
if ($isSiteAdmin || ($mayModify && $isAclTagger)):
?>
<span class="btn btn-inverse noPrint addGalaxy" data-target-type="<?php echo h($target_type);?>" data-target-id="<?php echo h($target_id); ?>" role="button" tabindex="0" aria-label="<?php echo __('Add new cluster');?>" style="padding: 1px 5px !important;font-size: 12px !important;"><?php echo __('Add');?></span>
<span class="btn btn-inverse noPrint addGalaxy" data-target-type="<?php echo h($target_type);?>" data-target-id="<?php echo h($target_id); ?>" role="button" tabindex="0" aria-label="<?php echo __('Add new cluster');?>" title="<?php echo __('Add new cluster');?>" style="padding: 1px 5px !important;font-size: 12px !important;"><?php echo __('Add');?></span>
<?php
endif;
?>

View File

@ -0,0 +1,230 @@
<?php
/**
* Generic select picker
*/
/** Config **/
$select_threshold = 7; // threshold above which pills will be replace by a select (unused if multiple is > 1)
$defaults_options = array(
'select_options' => array(
// 'multiple' => '', // set to add possibility to pick multiple options in the select
//'placeholder' => '' // set to replace the default placeholder text
),
'chosen_options' => array(
'width' => '85%',
'search_contains' => true, // matches starting from anywhere within a word
//'no_results_text' => '', // set to replace the default no result text after filtering
//'max_selected_options' => 'Infinity' // set to replace the max selected options
'disable_search_threshold' => 10,
'allow_single_deselect' => true,
),
'multiple' => 0,
'functionName' => '', // function to be called on submit
'submitButtonText' => 'Submit',
'disabledSubmitButton' => false, // wether to not draw the submit button
'flag_redraw_chosen' => false // should chosen picker be redraw at drawing time
);
/** prevent exception if not set **/
$options = isset($options) ? $options : array();
$items = isset($items) ? $items : array();
// merge options with defaults
$defaults = array_replace_recursive($defaults_options, $options);
// enforce consistency
if ($defaults['multiple'] == 0) {
unset($defaults['select_options']['multiple']);
} else { // multiple enabled
$defaults['chosen_options']['max_selected_options'] = $defaults['multiple'] == -1 ? 'Infinity' : $defaults['multiple'];
$defaults['select_options']['multiple'] = '';
$select_threshold = 0;
}
$use_select = count($items) > $select_threshold;
?>
<script>
function execAndClose(elem, alreadyExecuted) {
var dismissid = $(elem).closest('div.popover').attr('data-dismissid');
$('[data-dismissid="' + dismissid + '"]').popover('destroy');
}
function setupChosen(id, redrawChosen) {
var $elem = $('#'+id);
var chosen_options = <?php echo json_encode($defaults['chosen_options']); ?>;
$elem.chosen(chosen_options);
if (!$elem.prop('multiple')) { // not multiple, selection trigger next event
$elem.change(function(event, selected) {
var fn = $elem.data('functionname');
if (fn !== undefined) {
fn = window[fn];
submitFunction(this, fn);
} else {
select = this;
$select = $(select);
var endpoint;
if (selected !== undefined) {
endpoint = selected.selected;
} else { // for obscure reasons, `selected` variable is not set in some cases
endpoint = $(event.target).val();
}
if (endpoint === '') {
$wrapper = $select.closest('div').find('div.generic-picker-wrapper');
$wrapper.hide(0);
} else {
$select.data('endpoint', endpoint);
fetchRequestedData($select);
}
}
});
}
// hack to add template into the div
var $chosenContainer = $elem.parent().find('.chosen-container');
$elem.on('chosen:showing_dropdown chosen:searchdone keyup change', function() {
redrawChosenWithTemplate($elem, $chosenContainer)
});
if (redrawChosen) {
redrawChosenWithTemplate($elem, $chosenContainer);
}
}
function redrawChosenWithTemplate($select, $chosenContainer) {
var optionLength = $select.find('option').length;
if (optionLength > 1000) {
$chosenContainer.parent().find('.generic-picker-wrapper-warning-text').show(0)
} else {
$chosenContainer.find('.generic-picker-wrapper-warning-text').hide(0)
var $matches = $chosenContainer.find('.chosen-results .active-result, .chosen-single > span, .search-choice > span');
$matches.each(function() {
var $item = $(this);
var index = $item.data('option-array-index');
var $option;
if (index !== undefined) {
$option = $select.find('option:eq(' + index + ')');
} else { // if it is a `chosen-single span`, don't have index
var text = $item.text();
$option = $select.find('option:contains(' + text + ')');
}
var template = $option.data('template');
var res = "";
if (template !== undefined && template !== '') {
var template = atob(template);
var temp = doT.template(template);
var templateData = JSON.parse(atob($option.data('templatedata')));
res = temp(templateData);
$item.html(res);
}
})
}
}
// Used to keep the popover arrow at the correct place regardless of the popover content
function syncPopoverArrow($arrow, $wrapper, content) {
var ar_pos = $arrow.position();
$wrapper.html(content);
$wrapper.show();
// redraw popover
if (ar_pos !== undefined) {
$arrow.css('top', ar_pos.top + 'px');
$arrow.css('left', ar_pos.left + 'px');
}
}
// can either call a function or fetch requested data
function fetchRequestedData(clicked) {
var $clicked = $(clicked);
var $wrapper = $clicked.closest('div').find('div.generic-picker-wrapper');
$.ajax({
dataType:"html",
async: true,
cache: false,
beforeSend: function() {
var loadingHtml = '<div style="height: 40px; width: 40px; left: 50%; position: relative;"><div class="spinner" style="height: 30px; width: 30px;"></div></div>';
var $arrow = $clicked.closest('div.popover').find('div.arrow');
var $wrapper = $clicked.closest('div').find('div.generic-picker-wrapper');
syncPopoverArrow($arrow, $wrapper, loadingHtml)
},
success:function (data, textStatus) {
$wrapper = $clicked.closest('div').find('div.generic-picker-wrapper');
var $arrow = $clicked.closest('div.popover').find('div.arrow');
syncPopoverArrow($arrow, $wrapper, data)
},
error:function() {
$wrapper = $clicked.closest('div').find('div.generic-picker-wrapper');
$wrapper.html('<div class="alert alert-error" style="margin-bottom: 0px;">Something went wrong - the queried function returned an exception. Contact your administrator for further details (the exception has been logged).</div>');
},
url: $clicked.data('endpoint')
});
}
function submitFunction(clicked, callback) {
var $clicked = $(clicked);
var $select = $clicked.parent().find('select');
var selected, additionalData;
if ($select.length > 0) {
selected = $select.val();
additionalData = $select.find(":selected").data('additionaldata');
} else {
selected = $clicked.attr('value');
additionalData = $clicked.data('additionaldata');
}
execAndClose(clicked);
callback(selected, additionalData);
}
</script>
<div class="generic_picker">
<div class='generic-picker-wrapper-warning-text alert alert-error <?php echo (count($items) > 1000 ? '' : 'hidden'); ?>' style="margin-bottom: 5px;">
<i class="fa fa-exclamation-triangle"></i>
<?php echo __('Due to the large number of options, no contextual information is provided.'); ?>
</div>
<?php if ($use_select): ?>
<?php
$select_id = h(uniqid()); // used to only register the listener on this select (allowing nesting)
$flag_addPills = false;
?>
<select id="<?php echo $select_id; ?>" style="height: 100px; margin-bottom: 0px;" <?php echo h($this->GenericPicker->add_select_params($defaults)); ?>>
<option></option>
<?php
foreach ($items as $k => $param) {
if (isset($param['isPill']) && $param['isPill']) {
$flag_addPills = true;
continue;
} else {
echo $this->GenericPicker->add_option($param, $defaults);
}
}
?>
</select>
<?php if ($defaults['multiple'] != 0 && !$defaults['disabledSubmitButton']): ?>
<button class="btn btn-primary" onclick="submitFunction(this, <?php echo $defaults['functionName']; ?>)"><?php echo h($defaults['submitButtonText']); ?></button>
<?php endif; ?>
<?php if ($flag_addPills): // add forced pills ?>
<ul class="nav nav-pills">
<?php foreach ($items as $k => $param): ?>
<?php if (isset($param['isPill']) && $param['isPill']): ?>
<?php echo $this->GenericPicker->add_pill($param, $defaults); ?>
<?php endif; ?>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<script>
$(document).ready(function() {
setupChosen("<?php echo $select_id; ?>", <?php echo ($defaults['flag_redraw_chosen'] === true ? 'true' : 'false') ?>);
});
</script>
<?php elseif (count($items) > 0): ?>
<ul class="nav nav-pills">
<?php foreach ($items as $k => $param): ?>
<?php echo $this->GenericPicker->add_pill($param, $defaults); ?>
<?php endforeach; ?>
</ul>
<?php else: ?>
<span style="margin-left: 15px;"><?php echo __('Nothing to pick'); ?></span>
<?php endif; ?>
<div class='generic-picker-wrapper hidden'></div>
</div>

View File

@ -117,15 +117,17 @@
</ul>
</li>
<?php if ($isAclSync || $isAdmin): ?>
<?php if ($isAclSync || $isAdmin || $hostOrgUser): ?>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<?php echo __('Sync Actions');?>
<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="<?php echo $baseurl;?>/servers/index"><?php echo __('List Servers');?></a></li>
<?php if ($isSiteAdmin): ?>
<?php if ($isAclSync || $isAdmin): ?>
<li><a href="<?php echo $baseurl;?>/servers/index"><?php echo __('List Servers');?></a></li>
<?php endif; ?>
<?php if ($isSiteAdmin || $hostOrgUser): ?>
<li><a href="<?php echo $baseurl;?>/feeds/index"><?php echo __('List Feeds');?></a></li>
<?php endif;?>
</ul>

View File

@ -53,13 +53,9 @@
'url' => '/attributes/add/' . $event['Event']['id'],
'text' => __('Add Attribute')
));
echo $this->element('/side_menu_link', array(
'onClick' => array(
'function' => 'getPopup',
'params' => array($event['Event']['id'], 'objectTemplates', 'objectChoice')
),
'text' => __('Add Object')
));
echo '<li>';
echo '<a href="#" onclick="popoverPopup(this, ' . h($event['Event']['id']) . ', \'objectTemplates\', \'objectMetaChoice\')"> ' . __('Add Object') . '</a>';
echo '</li>';
echo $this->element('/side_menu_link', array(
'element_id' => 'addAttachment',
'url' => '/attributes/add_attachment/' . $event['Event']['id'],
@ -122,6 +118,14 @@
'class' => 'publishButtons not-published ' . $publishButtons,
'text' => __('Publish (no email)')
));
echo $this->element('/side_menu_link', array(
'onClick' => array(
'function' => 'publishPopup',
'params' => array($event['Event']['id'], 'unpublish')
),
'class' => (isset($event['Event']['published']) && (1 == $event['Event']['published'] && $mayModify)) ? '' : 'hidden',
'text' => __('Unpublish')
));
if (Configure::read('MISP.delegation')) {
if ((Configure::read('MISP.unpublishedprivate') || (isset($event['Event']['distribution']) && $event['Event']['distribution'] == 0)) && (!isset($delegationRequest) || !$delegationRequest) && ($isSiteAdmin || (isset($isAclDelegate) && $isAclDelegate))) {
echo $this->element('/side_menu_link', array(
@ -352,24 +356,42 @@
break;
case 'sync':
if ($menuItem === 'previewEvent' && $isSiteAdmin) : ?>
<li class="active"><?php echo $this->Html->link(__('Explore Remote Event'), array('controller' => 'servers', 'action' => 'previewEvent', h($server['Server']['id']), h($event['Event']['id']))); ?></li>
<li><?php echo $this->Form->postLink(__('Fetch This Event'), '/servers/pull/' . $server['Server']['id'] . '/' . $event['Event']['id'], null, __('Are you sure you want to fetch and save this event on your instance?', $this->Form->value('Server.id'))); ?></li>
<li><?php echo $this->Html->link(__('Explore Remote Server'), array('controller' => 'servers', 'action' => 'previewIndex', h($server['Server']['id']))); ?></li>
<?php endif;
if ($menuItem === 'previewIndex' && $isSiteAdmin) : ?>
<li class="active"><?php echo $this->Html->link(__('Explore Remote Server'), array('controller' => 'servers', 'action' => 'previewIndex', h($id))); ?></li>
<?php endif; ?>
<?php if ($menuItem === 'edit' && $isSiteAdmin): ?>
<li class="active"><?php echo $this->Html->link(__('Edit Server'), array('controller' => 'servers', 'action' => 'edit')); ?></li>
<li><?php echo $this->Form->postLink(__('Delete'), array('action' => 'delete', $this->Form->value('Server.id')), null, __('Are you sure you want to delete # %s?', $this->Form->value('Server.id'))); ?></li>
<li class="divider"></li>
<?php endif; ?>
<li id='liindex'><?php echo $this->Html->link(__('List Servers'), array('controller' => 'servers', 'action' => 'index'));?></li>
<?php if ($isSiteAdmin): ?>
<li id='liadd'><?php echo $this->Html->link(__('New Server'), array('controller' => 'servers', 'action' => 'add')); ?></li>
<?php endif;?>
<?php
if ($menuItem === 'previewEvent' && ($isSiteAdmin || $hostOrg)) {
echo sprintf(
'<li>%s</li><li class="active">%s</li>',
$this->Html->link(__('Explore Remote Server'), array('controller' => 'servers', 'action' => 'previewIndex', h($server['Server']['id']))),
$this->Html->link(__('Explore Remote Event'), array('controller' => 'servers', 'action' => 'previewEvent', h($server['Server']['id']), h($event['Event']['id'])))
);
}
if ($menuItem === 'previewEvent' && $isSiteAdmin) {
echo sprintf(
'<li>%s</li>',
$this->Form->postLink(__('Fetch This Event'), '/servers/pull/' . $server['Server']['id'] . '/' . $event['Event']['id'], null, __('Are you sure you want to fetch and save this event on your instance?', $this->Form->value('Server.id')))
);
}
if ($menuItem === 'previewIndex' && ($isSiteAdmin || $hostOrg)) {
echo sprintf(
'<li class="active">%s</li>',
$this->Html->link(__('Explore Remote Server'), array('controller' => 'servers', 'action' => 'previewIndex', h($id)))
);
}
if ($menuItem === 'edit' && $isSiteAdmin) {
echo sprintf(
'<li class="active">%s</li><li>%s</li><li class="divider"></li>',
$this->Html->link(__('Edit Server'), array('controller' => 'servers', 'action' => 'edit')),
$this->Form->postLink(__('Delete'), array('action' => 'delete', $this->Form->value('Server.id')), null, __('Are you sure you want to delete # %s?', $this->Form->value('Server.id')))
);
}
echo sprintf(
'<li id="liindex">%s</li>',
$this->Html->link(__('List Servers'), array('controller' => 'servers', 'action' => 'index'))
);
if ($isSiteAdmin) {
echo sprintf(
'<li id="liadd">%s</li>',
$this->Html->link(__('New Server'), array('controller' => 'servers', 'action' => 'add'))
);
}
break;
case 'admin':
@ -511,19 +533,54 @@
endif;
break;
case 'feeds': ?>
<li id='liindex'><a href="<?php echo $baseurl;?>/feeds/index"><?php echo __('List Feeds');?></a></li>
<li id='liadd'><a href="<?php echo $baseurl;?>/feeds/add"><?php echo __('Add Feed');?></a></li>
<li id='liadd'><a href="<?php echo $baseurl;?>/feeds/importFeeds"><?php echo __('Import Feeds from JSON');?></a></li>
<li id='licompare'><a href="<?php echo $baseurl;?>/feeds/compareFeeds"><?php echo __('Feed overlap analysis matrix');?></a></li>
<li id='liexport'><a href="<?php echo $baseurl;?>/feeds/index.json" download="feed_index.json"><?php echo __('Export Feed settings');?></a></li>
<?php if ($menuItem === 'edit'): ?>
<li class="active"><a href="#"><?php echo __('Edit Feed');?></a></li>
<?php elseif ($menuItem === 'previewIndex'): ?>
<li id='lipreviewIndex'><a href="<?php echo $baseurl;?>/feeds/previewIndex/<?php echo h($feed['Feed']['id']); ?>"><?php echo __('PreviewIndex');?></a></li>
<?php elseif ($menuItem === 'previewEvent'): ?>
<li id='lipreviewEvent'><a href="<?php echo $baseurl;?>/feeds/previewEvent/<?php echo h($feed['Feed']['id']); ?>/<?php echo h($id);?>"><?php echo __('PreviewEvent');?></a></li>
<?php endif;
case 'feeds':
echo sprintf(
'<li id="liindex"><a href="%s/feeds/index">%s</a></li>',
$baseurl,
__('List Feeds')
);
if ($isSiteAdmin) {
echo sprintf(
'<li id="liadd"><a href="%s/feeds/add">%s</a></li>',
$baseurl,
__('Add Feed')
);
echo sprintf(
'<li id="liimport"><a href="%s/feeds/importFeeds">%s</a></li>',
$baseurl,
__('Import Feeds from JSON')
);
}
echo sprintf(
'<li id="licompare"><a href="%s/feeds/compareFeeds">%s</a></li>',
$baseurl,
__('Feed overlap analysis matrix')
);
echo sprintf(
'<li id="liexport"><a href="%s/feeds/index.json" download="feed_index.json">%s</a></li>',
$baseurl,
__('Export Feed settings')
);
if ($isSiteAdmin) {
if ($menuItem === 'edit') {
echo '<li class="active"><a href="#">' . __('Edit Feed') . '</a></li>';
} else if ($menuItem === 'previewIndex') {
echo sprintf(
'<li id="lipreviewIndex"><a href="%s/feeds/previewIndex/%s"></a></li>',
$baseurl,
h($feed['Feed']['id']),
__('PreviewIndex')
);
} else if ($menuItem === 'previewEvent') {
echo sprintf(
'<li id="lipreviewEvent"><a href="%s/feeds/previewEvent/%s/%s">%s</a></li>',
$baseurl,
h($feed['Feed']['id']),
h($id),
__('PreviewEvent')
);
}
}
break;
case 'news': ?>

View File

@ -1,3 +1,6 @@
<?php
$clusetersNamesMapping = array(); // used to map name with id for the chosen select
?>
<div class="attack-matrix-options" style="right: initial; background: transparent;">
<ul id="attack-matrix-tabscontroller" class="nav nav-tabs" style="margin-bottom: 2px;">
<?php
@ -78,6 +81,7 @@ foreach($attackTactic as $tactic):
$tagName = $clusters[$i]['tag_name'];
$score = empty($scores[$tagName]) ? 0 : $scores[$tagName];
$name = join(" ", array_slice(explode(" ", $clusters[$i]['value']), 0, -2)); // remove " - external_id"
$clusetersNamesMapping[$clusterId] = $name;
$td .= ' class="heatCell matrix-interaction ' . ($pickingMode ? 'cell-picking"' : '"');
$td .= isset($colours[$tagName]) ? ' style="background: ' . h($colours[$tagName]) . '; color: ' . h($this->TextColour->getTextColour($colours[$tagName])) . '"' : '' ;
$td .= ' data-score="'.h($score).'"';
@ -109,8 +113,17 @@ foreach($attackTactic as $tactic):
</div>
</div>
<?php if($pickingMode): ?>
<div role="button" tabindex="0" aria-label="<?php echo __('Submit');?>" title="<?php echo __('Submit');?>" class="templateChoiceButton btn-matrix-submit" onClick="cancelPopoverForm('#popover_form_large');"><?php echo __('Submit'); ?></div>
<div style="padding: 5px;">
<select id="attack-matrix-chosen-select" style="width: 100%; margin: 0px;" multiple>
<?php
foreach ($clusetersNamesMapping as $clusterId => $clusterName) {
echo '<option value=' . h($clusterId) .'>' . h($clusterName) . '</option>';
}
?>
</select>
</div>
<div role="button" tabindex="0" aria-label="<?php echo __('Cancel');?>" title="<?php echo __('Cancel');?>" class="templateChoiceButton templateChoiceButtonLast" onClick="cancelPopoverForm('#popover_form_large');"><?php echo __('Cancel'); ?></div>
<?php endif; ?>

View File

@ -12,7 +12,7 @@
'mayModify' => $mayModify,
'isAclTagger' => $isAclTagger,
'data' => $object['Galaxy'],
'target_id' => $object['Event']['id'],
'target_id' => $scope == 'event' ? $object['Event']['id'] : $object['Attribute']['id'],
'target_type' => $scope
));
?>

View File

@ -3,19 +3,22 @@
echo $this->Form->create('Event', array('style' => 'margin:0px;', 'id' => 'PromptForm', 'url' => '/events/' . $type . '/' . $id));
$extraTitle = "";
if ($type == 'publish') $extraTitle = ' (no email)';
$message = __('Publish Event%s', $extraTitle);
if ($type === 'unpublish') {
$message = __('Unpublish Event%s', $extraTitle);
}
?>
<legend><?php echo __('Publish Event%s', $extraTitle);?></legend>
<legend><?php echo $message;?></legend>
<div style="padding-left:5px;padding-right:5px;padding-bottom:5px;">
<?php
if ($type == 'alert'):
?>
<p><?php echo __('Are you sure this event is complete and everyone should be informed?');?></p>
<?php
else:
?>
<p><?php echo __('Publish but do NOT send alert email? Only for minor changes!');?></p>
<?php
endif;
if ($type == 'alert') {
echo '<p>' . __('Are you sure this event is complete and everyone should be informed?') . '</p>';
} else if ($type === 'unpublish') {
echo '<p>' . __('Are you sure you wish to unpublish the event?') . '</p>';
} else {
echo '<p>' . __('Publish but do NOT send alert email? Only for minor changes!') . '</p>';
}
?>
<table>
<tr>

View File

@ -164,8 +164,17 @@
<dt class="hidden"></dt><dd class="hidden"></dd>
<dt class="background-red bold not-published <?php echo ($event['Event']['published'] == 0) ? '' : 'hidden'; ?>"><?php echo __('Published');?></dt>
<dd class="background-red bold not-published <?php echo ($event['Event']['published'] == 0) ? '' : 'hidden'; ?>"><?php echo __('No');?></dd>
<dt class="bold published <?php echo ($event['Event']['published'] == 0) ? 'hidden' : ''; ?>"><?php echo __('Published');?></dt>
<dd class="green bold published <?php echo ($event['Event']['published'] == 0) ? 'hidden' : ''; ?>"><?php echo __('Yes');?></dd>
<?php
$publish_status_class = ($event['Event']['published'] == 0) ? 'hidden' : '';
echo sprintf(
'<dt class="bold published %s">%s</dt><dd class="published %s"><span class="green bold">%s</span> (%s)</dd>',
$publish_status_class,
__('Published'),
$publish_status_class,
__('Yes'),
(empty($event['Event']['publish_timestamp'])) ? 'N/A' : date('Y-m-d H:i:s', ($event['Event']['publish_timestamp']))
);
?>
<dt><?php echo __('#Attributes');?></dt>
<dd><?php echo h($attribute_count);?></dd>
<dt><?php echo __('Last change');?></dt>
@ -338,6 +347,35 @@
<?php
endif;
endif;
if (!empty($event['Server']) || !empty($event['Event']['ServerCount'])):
?>
<h3>Related Server</h3>
<?php
if (!empty($event['Server'])):
foreach ($event['Server'] as $relatedServer):
$relatedData = array('Name' => $relatedServer['name'], 'URL' => $relatedServer['url']);
$popover = '';
foreach ($relatedData as $k => $v) {
$popover .= '<span class=\'bold\'>' . h($k) . '</span>: <span class="blue">' . h($v) . '</span><br />';
}
?>
<span style="white-space: nowrap;">
<form action="<?php echo $baseurl; ?>/servers/previewIndex/<?php echo h($relatedServer['id']); ?>" method="post" style="margin:0px;">
<input type="hidden" name="data[Feed][eventid]" value="<?php echo h(json_encode($relatedServer['event_uuids'], true)); ?>">
<input type="submit" class="linkButton useCursorPointer" value="<?php echo h($relatedServer['name']) . ' (' . $relatedServer['id'] . ')'; ?>" data-toggle="popover" data-content="<?php echo h($popover); ?>" data-trigger="hover" />
</form>
</span>
<?php
endforeach;
elseif (!empty($event['Event']['FeedCount'])):
?>
<span>
<?php echo __('This event has ');?><span class="bold"><?php echo h($event['Event']['FeedCount']); ?></span>
<?php echo __('correlations with data contained within the various feeds, however, due to the large number of attributes the actual feed correlations are not shown. Click <a href="%s\/overrideLimit:1">here</a> to refresh the page with the feed data loaded.', h($this->here));?>
</span>
<?php
endif;
endif;
?>
<?php if (!empty($event['Event']['warnings'])): ?>
<div class="warning_container" style="width:80%;">
@ -426,7 +464,7 @@ function enable_correlation_graph() {
}
function enable_attack_matrix() {
$.get("/events/viewMitreAttackMatrix/<?php echo h($event['Event']['id']); ?>", function(data) {
$.get("/events/viewMitreAttackMatrix/<?php echo h($event['Event']['id']); ?>/event/1", function(data) {
$("#attackmatrix_div").html(data);
});
}

View File

@ -1,3 +0,0 @@
<?php
echo $this->element('view_mitre_attack_matrix');
?>

View File

@ -21,7 +21,7 @@
?>
<th>
<div data-toggle="popover" data-content="<?php echo $popover; ?>" data-trigger="hover">
<?php echo h($item['Feed']['id']); ?>
<?php echo (empty($item['Feed']['is_misp_server']) ? 'F' : 'S') . h($item['Feed']['id']); ?>
</div>
</th>
<?php
@ -38,7 +38,15 @@
<tr>
<td class="short">
<div data-toggle="popover" data-content="<?php echo $popover;?>" data-trigger="hover">
<?php echo h($item['Feed']['id']) . ' ' . h($item['Feed']['name']); ?>&nbsp;
<?php
echo sprintf(
'%s%s %s%s',
empty($item['Feed']['is_misp_server']) ? 'Feed #' : 'Server #',
h($item['Feed']['id']),
empty($item['Feed']['is_misp_server']) ? '' : '(<span class="blue bold">MISP</span>) ',
h($item['Feed']['name'])
);
?>
</div>
</td>
<?php

View File

@ -196,7 +196,7 @@ foreach ($feeds as $item):
else:
echo __('Not cached');
endif;
if ($item['Feed']['caching_enabled']):
if ($item['Feed']['caching_enabled'] && $isSiteAdmin):
?>
<a href="<?php echo $baseurl;?>/feeds/cacheFeeds/<?php echo h($item['Feed']['id']); ?>" title="Cache feed"><span class="icon-download-alt"></span></a>
<?php
@ -206,12 +206,14 @@ foreach ($feeds as $item):
<td class="short action-links">
<?php
echo $this->Html->link('', array('action' => 'previewIndex', $item['Feed']['id']), array('class' => 'icon-search', 'title' => __('Explore the events remotely')));
if (!isset($item['Feed']['event_error'])) {
if (!isset($item['Feed']['event_error']) && $isSiteAdmin) {
if ($item['Feed']['enabled']) echo $this->Html->link('', array('action' => 'fetchFromFeed', $item['Feed']['id']), array('class' => 'icon-download', 'title' => __('Fetch all events')));
}
if ($isSiteAdmin):
?>
<a href="<?php echo $baseurl;?>/feeds/edit/<?php echo h($item['Feed']['id']); ?>"><span class="icon-edit" title="Edit">&nbsp;</span></a>
<?php echo $this->Form->postLink('', array('action' => 'delete', h($item['Feed']['id'])), array('class' => 'icon-trash', 'title' => __('Delete')), __('Are you sure you want to permanently remove the feed (%s)?', h($item['Feed']['name']))); ?>
<a href="<?php echo $baseurl;?>/feeds/edit/<?php echo h($item['Feed']['id']); ?>"><span class="icon-edit" title="Edit">&nbsp;</span></a>
<?php echo $this->Form->postLink('', array('action' => 'delete', h($item['Feed']['id'])), array('class' => 'icon-trash', 'title' => __('Delete')), __('Are you sure you want to permanently remove the feed (%s)?', h($item['Feed']['name']))); ?>
<?php endif; ?>
<a href="<?php echo $baseurl;?>/feeds/view/<?php echo h($item['Feed']['id']); ?>.json" title="<?php echo __('Download feed metadata as JSON');?>" download><span class="fa fa-cloud-download black"></span></a>
</td>
</tr><?php

View File

@ -62,7 +62,7 @@
</td>
<td ondblclick="document.location.href ='<?php echo $eventViewURL . h($uuid);?>'" class="short"><?php echo h($event['timestamp']); ?></td>
<td class="short action-links">
<?php if ($feed['Feed']['enabled']) echo $this->Form->postLink('', '/feeds/getEvent/' . $id . '/' . $uuid, array('class' => 'icon-download', 'title' => 'Fetch the event'), __('Are you sure you want to fetch and save this event on your instance?', $this->Form->value('Feed.id'))); ?>
<?php if ($feed['Feed']['enabled'] && $isSiteAdmin) echo $this->Form->postLink('', '/feeds/getEvent/' . $id . '/' . $uuid, array('class' => 'icon-download', 'title' => 'Fetch the event'), __('Are you sure you want to fetch and save this event on your instance?', $this->Form->value('Feed.id'))); ?>
<a href='<?php echo $eventViewURL . h($uuid);?>' class = "icon-list-alt" title = "<?php echo __('View');?>"></a>
</td>
</tr>

View File

@ -1,65 +1,16 @@
<div class="popover_choice select_cluster">
<legend><?php echo __('Select Cluster');?></legend>
<div class="hidden">
<?php
echo $this->Form->create('Galaxy', array('url' => '/galaxies/attachCluster/' . $target_type . '/' . $target_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="<?php echo __('search clusters…');?>"/>
</div>
<div class="popover_choice_main" id ="popover_choice_main">
<table style="width:100%;">
<div class="hidden">
<?php
foreach ($clusters as $namespace => $cluster_data):
foreach ($cluster_data as $k => $cluster):
$title = isset($cluster['description']) ? $cluster['description'] : $cluster['value'];
echo $this->Form->create('Galaxy', array('url' => '/galaxies/attachMultipleClusters/' . h($target_id) . '/' . h($target_type), 'style' => 'margin:0px;'));
echo $this->Form->input('target_ids', array('type' => 'text'));
echo $this->Form->input('attribute_ids', array('style' => 'display:none;', 'label' => false));
echo $this->Form->end();
?>
<tr id="field_<?php echo h($cluster['id']); ?>" style="border-bottom:1px solid black;" class="templateChoiceButton filterableButton">
<td class="clusterSelectChoice" data-target-type="<?php echo h($target_type); ?>" data-target-id="<?php echo h($target_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']) . ' (' . h($cluster['type']) . ')'; ?></td>
</tr>
<?php
endforeach;
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-target-type="<?php echo h($target_type); ?>" data-event-id="<?php echo h($target_id); ?>" title="Select Galaxy"><?php echo __('Back to Galaxy Selection');?></td>
</tr>
</table>
</div>
<div role="button" tabindex="0" aria-label="<?php echo __('Cancel');?>" title="<?php echo __('Cancel');?>" class="templateChoiceButton templateChoiceButtonLast" onClick="cancelPopoverForm();"><?php echo __('Cancel');?></div>
</div>
<script type="text/javascript">
var lookup_table = <?php echo json_encode($lookup_table); ?>;
<?php echo $this->element('generic_picker'); ?>
<script>
$(document).ready(function() {
resizePopoverBody();
$("#clusterFilterField").focus();
});
$('.clusterSelectBack').click(function() {
getPopup($(this).data('target-type') + '/' + $(this).data('target-id'), 'galaxies', 'selectGalaxy');
});
$('.clusterSelectChoice').click(function() {
quickSubmitGalaxyForm($(this).data('target-id'), $(this).data('cluster-id'), $(this).data('target-type'));
});
$('#clusterFilterField').keyup(function() {
var filterString = $("#clusterFilterField").val().toLowerCase();
$('.filterableButton').hide();
$.each(lookup_table, function(namespace, namespace_data) {
$.each(namespace_data, function(index, value) {
var found = false;
if (index.toLowerCase().indexOf(filterString) != -1) {
$.each(value, function(k, v) {
$('#field_' + v).show();
});
}
});
});
});
$(window).resize(function() {
resizePopoverBody();
$('#GalaxyAttributeIds').attr('value', getSelected());
});
</script>

View File

@ -1,32 +0,0 @@
<div class="popover_choice select_galaxy_source">
<legend><?php echo __('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 role="button" tabindex="0" aria-label="<?php echo __('All clusters');?>" title="<?php echo __('All clusters');?>" style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($target_id) . '/' . h($target_type); ?>/0', 'galaxies', 'selectCluster');"><?php echo __('All Galaxies');?></td>
</tr>
<?php foreach ($galaxies as $galaxy): ?>
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
<?php if ($galaxy['Galaxy']['id'] != -1): ?>
<td role="button" tabindex="0" aria-label="<?php echo h($galaxy['Galaxy']['name']); ?>" title="<?php echo h($galaxy['Galaxy']['name']); ?>" style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($target_id) . "/" . h($target_type); ?>/<?php echo h($galaxy['Galaxy']['id']);?>', 'galaxies', 'selectCluster');">Galaxy: <?php echo h($galaxy['Galaxy']['name']); ?></td>
<?php else: ?>
<td role="button" tabindex="0" aria-label="<?php echo h($galaxy['Galaxy']['name']); ?>" title="<?php echo h($galaxy['Galaxy']['name']); ?>" style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getMitreMatrixPopup('<?php echo h($target_id) . "/" . h($target_type); ?>');">
<img src="<?php echo h($galaxy['Galaxy']['icon']); ?>" style="margin-right: 8px; height: 25px;"/>
<?php echo h($galaxy['Galaxy']['name']); ?>
</td>
<?php endif; ?>
</tr>
<?php endforeach; ?>
</table>
</div>
<div role="button" tabindex="0" aria-label="<?php echo __('Cancel');?>" title="<?php echo __('Cancel');?>" class="templateChoiceButton templateChoiceButtonLast" onClick="cancelPopoverForm();"><?php echo __('Cancel');?></div>
</div>
<script type="text/javascript">
$(document).ready(function() {
resizePopoverBody();
});
$(window).resize(function() {
resizePopoverBody();
});
</script>

View File

@ -1,25 +0,0 @@
<div class="popover_choice select_galaxy_namespace_source">
<legend><?php echo __('Select Galaxy Namespace 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 role="button" tabindex="0" aria-label="<?php echo __('All namespaces');?>" title="<?php echo __('All namespaces');?>" style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($target_id) . '/' . h($target_type); ?>/0', 'galaxies', 'selectGalaxy');"><?php echo __('All Namespaces');?></td>
</tr>
<?php foreach ($namespaces as $namespace): ?>
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
<td role="button" tabindex="0" aria-label="<?php echo h($namespace); ?>" title="<?php echo h($namespace); ?>" style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($target_id) . "/" . h($target_type); ?>/<?php echo h($namespace)?>', 'galaxies', 'selectGalaxy');"><?php echo h($namespace); ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
<div role="button" tabindex="0" aria-label="<?php echo __('Cancel');?>" title="<?php echo __('Cancel');?>" class="templateChoiceButton templateChoiceButtonLast" onClick="cancelPopoverForm();"><?php echo __('Cancel');?></div>
</div>
<script type="text/javascript">
$(document).ready(function() {
resizePopoverBody();
});
$(window).resize(function() {
resizePopoverBody();
});
</script>

View File

@ -0,0 +1,99 @@
<?php
App::uses('AppHelper', 'View/Helper');
/* Class containing functions to ease the creation of the GenericPicker */
class GenericPickerHelper extends AppHelper {
function add_select_params($options) {
$select_html = '';
foreach ($options['select_options'] as $option => $value) {
$select_html .= $option . '=' . $value . ' ';
}
if (isset($options['functionName']) && $options['functionName'] !== "") {
$select_html .= ' data-functionname=' . $options['functionName'] .' ';
}
return $select_html;
}
function add_option($param, $defaults) {
$option_html = '<option';
if (isset($param['value'])) {
$option_html .= ' value=' . h($param['value']);
} else {
$option_html .= ' value=' . h($param['name']);
}
if (isset($param['additionalData'])) {
$additionalData = json_encode($param['additionalData']);
} else {
$additionalData = json_encode(array());
}
if (isset($param['template'])) {
$option_html .= ' data-template=' . base64_encode($param['template']);
}
if (isset($param['templateData'])) {
$option_html .= ' data-templatedata=' . base64_encode(json_encode($param['templateData']));
}
$option_html .= ' data-additionaldata=' . $additionalData;
if (isset($param['disabled']) && $param['disabled']) {
$option_html .= ' disabled';
} else if (isset($param['selected']) && $param['selected']) { // nonsense to pre-select if disabled
$option_html .= ' selected';
}
$option_html .= '>';
$option_html .= h($param['name']);
$option_html .= '</option>';
return $option_html;
}
function add_link_params($param, $defaults=array()) {
$param_html = ' ';
if (isset($param['functionName'])) {
$param_html .= 'onclick="execAndClose(this, ' . $param['functionName'] . ')" ';
} else { // fallback to default submit function
if ($defaults['functionName'] !== '') {
$param_html .= 'onclick="submitFunction(this, ' . $defaults['functionName'] . ')" ';
} else {
$param_html .= 'data-endpoint="' . h($param['value']) . '" ';
$param_html .= 'onclick="fetchRequestedData(this)" ';
}
}
$additionalData = json_encode(array());
foreach ($param as $paramName => $paramValue) {
if ($paramName === 'additionalData') {
$additionalData = json_encode($param['additionalData']);
} else if ($paramName === 'value') {
$param_html .= 'value="' . h($paramValue) . '" ';
} else if ($paramName === 'template' || $paramName === 'templateData') {
continue;
} else {
$param_html .= 'data-' . h($paramName). '="' . h($paramValue) . '" ';
}
}
$param_html .= ' data-additionaldata=' . $additionalData;
return $param_html;
}
function add_pill($param, $defaults=array()) {
$pill_html = '<li>';
$pill_html .= '<a href="#" data-toggle="pill" class="pill-pre-picker"';
$pill_html .= ' ' . $this->add_link_params($param, $defaults);
$pill_html .= '>';
if (isset($param['img'])) {
$pill_html .= '<img src="' . $param['img'] . '" style="margin-right: 5px; height: 14px;">';
} else if (isset($param['icon']) || isset($param['templateData']['icon'])) {
$icon = isset($param['icon']) ? $param['icon'] : $param['templateData']['icon'];
$pill_html .= '<span class="fa fa-' . $icon . '" style="margin-right: 5px;"></span>';
}
$pill_html .= h($param['name']) . '</a>';
$pill_html .= '</li>';
return $pill_html;
}
}
?>

View File

@ -29,6 +29,9 @@
echo $this->Html->script('jquery'); // Include jQuery library
echo $this->Html->script('misp-touch'); // touch interface support
echo $this->Html->script('jquery-ui'); // UI support
echo $this->Html->css('chosen.min');
echo $this->Html->script('chosen.jquery.min');
echo $this->Html->script('doT');
?>
</head>

View File

@ -1,57 +0,0 @@
<div class="popover_choice">
<legend><?php echo __('Select Object Category');?></legend>
<div class="popover_choice_main" id ="popover_choice_main">
<table style="width:100%;" id="MainTable">
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
<td role="button" tabindex="0" aria-label="<?php echo __('All meta-categories');?>" title="<?php echo __('All Objects');?>" style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="objectChoiceSelect('all');"><?php echo __('All Objects');?></td>
</tr>
</table>
</div>
<div role="button" tabindex="0" aria-label="<?php echo __('Cancel');?>" title="<?php echo __('Cancel');?>" class="templateChoiceButton templateChoiceButtonLast" onClick="cancelPopoverForm();"><?php echo __('Cancel');?></div>
</div>
<script type="text/javascript">
var choice = "categories";
var eventId = "<?php echo h($eventId);?>";
var templates = <?php echo json_encode($templates); ?>;
var template_categories = <?php echo json_encode($template_categories); ?>;
$(document).ready(function() {
resizePopoverBody();
populateObjectChoiceList(choice);
});
$(window).resize(function() {
resizePopoverBody();
});
function populateObjectChoiceList(choice) {
$("#MainTable").empty();
if (choice == "categories") {
template_categories.forEach(function(category) {
$("#MainTable").append(createObjectChoiceRowCategories(category));
});
} else {
templates[choice].forEach(function(element) {
$("#MainTable").append(createObjectChoiceRow(eventId, element));
});
$("#MainTable").append(createObjectChoiceRowCategories('categories'));
}
}
function createObjectChoiceRow(eventId, data) {
var html = '<tr style="border-bottom:1px solid black;" class="templateChoiceButton">';
var html = html + '<td role="button" tabindex="0" aria-label="' + data["description"] + '" title="' + data["description"] + '" style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="window.location=\'/objects/add/' + eventId + '/' + data["id"] + '\';">' + data["name"].charAt(0).toUpperCase() + data["name"].slice(1) + '</td>';
var html = html + '</tr>';
return html;
}
function createObjectChoiceRowCategories(data) {
var text = data;
if (text == 'categories') {
text = '<?php echo __('Back to categories');?>';
}
var html = '<tr style="border-bottom:1px solid black;" class="templateChoiceButton">';
var html = html + '<td role="button" tabindex="0" aria-label="' + (text[0].toUpperCase() + text.slice(1)) + '" title="' + (text[0].toUpperCase() + text.slice(1)) + '" style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="populateObjectChoiceList(\'' + data + '\');">' + (text[0].toUpperCase() + text.slice(1)) + '</td>';
var html = html + '</tr>';
return html;
}
</script>

View File

@ -3,6 +3,7 @@
<fieldset>
<legend><?php echo __('Add Server');?></legend>
<?php
echo '<h4 class="input clear">' . __('Instance identification') . '</h4>';
echo $this->Form->input('url', array(
'label' => __('Base URL'),
));
@ -25,8 +26,9 @@
endif;
?>
<div class="input clear" style="width:100%;">
<hr />
<p class="red"><?php echo __('Information about the organisation that will receive the events, typically the remote instance\'s host organisation.');?></p>
<hr />
<h4><?php echo __('Instance ownership and credentials'); ?></h4>
<p class="red"><?php echo __('Information about the organisation that will receive the events, typically the remote instance\'s host organisation.');?></p>
</div>
<div class = "input clear"></div>
<?php
@ -61,38 +63,25 @@
endif;
echo $this->Form->input('authkey', array(
));
?>
<div class = "input clear" style="width:100%;"><hr /></div>
<div class = "input clear"></div>
<?php
echo $this->Form->input('push', array(
));
echo $this->Form->input('pull', array(
));
?>
<div class = "input clear"></div>
<?php
echo '<div class = "input clear" style="width:100%;"><hr /></div>';
echo '<h4 class="input clear">' . __('Enabled synchronisation methods') . '</h4>';
echo $this->Form->input('push', array());
echo $this->Form->input('pull', array());
echo $this->Form->input('caching_enabled', array());
echo '<div class = "input clear" style="width:100%;"><hr /></div>';
echo $this->Form->input('unpublish_event', array(
'type' => 'checkbox',
));
?>
<div class = "input clear"></div>
<?php
echo '<div class="input clear"></div>';
echo $this->Form->input('publish_without_email', array(
'type' => 'checkbox',
));
?>
<div class = "input clear"></div>
<?php
echo '<div class="input clear"></div>';
echo $this->Form->input('self_signed', array(
'type' => 'checkbox',
));
?>
<div class = "input clear"></div>
<?php
echo '<div class="input clear"></div>';
echo $this->Form->input('skip_proxy', array('type' => 'checkbox', 'label' => 'Skip proxy (if applicable)'));
echo $this->Form->input('Server.submitted_cert', array(
'label' => '<b>' . __('Server certificate file') . '</b>',
'type' => 'file',

View File

@ -3,6 +3,7 @@
<fieldset>
<legend><?php echo __('Edit Server');?></legend>
<?php
echo '<h4 class="input clear">' . __('Instance identification') . '</h4>';
echo $this->Form->input('url', array(
'label' => __('Base URL'),
));
@ -25,7 +26,12 @@
endif;
?>
<div class="input clear"></div>
<div class="input clear" style="width:100%;">
<hr />
<h4><?php echo __('Instance ownership and credentials'); ?></h4>
<p class="red"><?php echo __('Information about the organisation that will receive the events, typically the remote instance\'s host organisation.');?></p>
</div>
<div class = "input clear"></div>
<?php
echo $this->Form->input('organisation_type', array(
'label' => __('Organisation Type'),
@ -63,40 +69,29 @@
<label for="ServerExternalUuid"><?php echo __('Remote Organisation\'s Uuid');?></label>
<input type="text" id="ServerExternalUuid" <?php if (isset($this->request->data['Server']['external_uuid'])) echo 'value="' . $this->request->data['Server']['external_uuid'] . '"';?>>
</div>
<div class = "input clear"></div>
<?php
echo '<div class="input clear"></div>';
echo $this->Form->input('authkey', array(
'placeholder' => __('Leave empty to use current key')
));
?>
<div class = "input clear"></div>
<?php
echo $this->Form->input('push', array(
));
echo $this->Form->input('pull', array(
));
?>
<div class = "input clear"></div>
<?php
echo '<div class = "input clear" style="width:100%;"><hr /></div>';
echo '<h4 class="input clear">' . __('Enabled synchronisation methods') . '</h4>';
echo $this->Form->input('push', array());
echo $this->Form->input('pull', array());
echo $this->Form->input('caching_enabled', array());
echo '<div class = "input clear" style="width:100%;"><hr /><h4>' . __('Misc settings') . '</h4></div>';
echo $this->Form->input('unpublish_event', array(
'type' => 'checkbox',
));
?>
<div class = "input clear"></div>
<?php
echo '<div class="input clear"></div>';
echo $this->Form->input('publish_without_email', array(
'type' => 'checkbox',
));
?>
<div class = "input clear"></div>
<?php
echo '<div class="input clear"></div>';
echo $this->Form->input('self_signed', array(
'type' => 'checkbox',
));
?>
<div class = "input clear"></div>
<?php
echo '<div class="input clear"></div>';
echo $this->Form->input('skip_proxy', array('type' => 'checkbox', 'label' => 'Skip proxy (if applicable)'));
?>
<div class="clear">

View File

@ -24,6 +24,7 @@
<th><?php echo $this->Paginator->sort('internal');?></th>
<th><?php echo $this->Paginator->sort('push');?></th>
<th><?php echo $this->Paginator->sort('pull');?></th>
<th><?php echo $this->Paginator->sort('caching_enabled', 'Cache');?></th>
<th><?php echo $this->Paginator->sort('unpublish_event (push event)');?></th>
<th><?php echo $this->Paginator->sort('publish_without_email (pull event)');?></th>
<th><?php echo $this->Paginator->sort('url');?></th>
@ -71,7 +72,42 @@ foreach ($servers as $server):
<td id="connection_test_<?php echo $server['Server']['id'];?>"><span role="button" tabindex="0" aria-label="<?php echo __('Test the connection to the remote instance');?>" title="<?php echo __('Test the connection to the remote instance');?>" class="btn btn-primary" style="line-height:10px; padding: 4px 4px;" onClick="testConnection('<?php echo $server['Server']['id'];?>');"><?php echo __('Run');?></span></td>
<td><span class="<?php echo ($server['Server']['internal']? 'icon-ok' : 'icon-remove'); ?>" title="<?php echo ($server['Server']['internal']? __('Internal instance that ignores distribution level degradation *WARNING: Only use this setting if you have several internal instances and the sync link is to an internal extension of the current MISP community*') : __('Normal sync link to an external MISP instance. Distribution degradation will follow the normal rules.')); ?>"></span></td>
<td><span class="<?php echo ($server['Server']['push']? 'icon-ok' : 'icon-remove'); ?>"></span><span class="short <?php if (!$server['Server']['push'] || empty($ruleDescription['push'])) echo "hidden"; ?>" data-toggle="popover" title="Distribution List" data-content="<?php echo $ruleDescription['push']; ?>"> (<?php echo __('Rules');?>)</span></td>
<td><span class="<?php echo ($server['Server']['pull']? 'icon-ok' : 'icon-remove'); ?>"></span><span class="short <?php if (!$server['Server']['pull'] || empty($ruleDescription['pull'])) echo "hidden"; ?>" data-toggle="popover" title="Distribution List" data-content="<?php echo $ruleDescription['pull']; ?>"> (<?php echo __('Rules');?>)</span>
<td><span class="<?php echo ($server['Server']['pull']? 'icon-ok' : 'icon-remove'); ?>"></span><span class="short <?php if (!$server['Server']['pull'] || empty($ruleDescription['pull'])) echo "hidden"; ?>" data-toggle="popover" title="Distribution List" data-content="<?php echo $ruleDescription['pull']; ?>"> (<?php echo __('Rules');?>)</span></td>
<td>
<?php
if ($server['Server']['caching_enabled']) {
if (!empty($server['Server']['cache_timestamp'])) {
$units = array('m', 'h', 'd');
$intervals = array(60, 60, 24);
$unit = 's';
$last = time() - $server['Server']['cache_timestamp'];
foreach ($units as $k => $v) {
if ($last > $intervals[$k]) {
$unit = $v;
$last = floor($last / $intervals[$k]);
} else {
break;
}
}
echo sprintf(
'<span class="blue bold">%s%s%s</span> %s',
__('Age: '),
$last,
$unit,
'<span class="icon-ok"></span>'
);
} else {
echo sprintf(
'<span class="red bold">%s</span> %s',
__('Not cached'),
'<span class="icon-ok"></span>'
);
}
} else {
echo '<span class="icon-remove"></span>';
}
?>
</td>
<td class="short"><span class="<?php echo ($server['Server']['unpublish_event'] ? 'icon-ok' : 'icon-remove'); ?>"></span></td>
<td class="short"><span class="<?php echo ($server['Server']['publish_without_email'] ? 'icon-ok' : 'icon-remove'); ?>"></span></td>
<td><?php echo h($server['Server']['url']); ?>&nbsp;</td>
@ -91,6 +127,9 @@ foreach ($servers as $server):
if ($server['Server']['push']) {
echo $this->Html->link('', array('action' => 'push', $server['Server']['id'], 'full'), array('class' => 'icon-upload', 'title' => __('Push all')));
}
if ($server['Server']['caching_enabled']) {
echo $this->Html->link('', array('action' => 'cache', $server['Server']['id']), array('class' => 'icon-download-alt', 'title' => __('Cache instance')));
}
?>
&nbsp;
<?php

View File

@ -90,7 +90,7 @@
<hr />
</div>
</fieldset>
<?php
$formats = array('Raw', 'JSON', 'HTML');
if (!empty($data['code']) && $data['code'] < 300) {
@ -110,7 +110,7 @@
}
echo '</div>';
}
if (!empty($data['data'])):
echo sprintf('<h3>%s</h3>', __('Response'));
echo sprintf('<div><span class="bold">%s</span>: %d</div>', __('Response code'), h($data['code']));
@ -148,8 +148,6 @@
echo $this->Html->script('moment-with-locales');
echo $this->Html->css('query-builder.default');
echo $this->Html->script('query-builder');
echo $this->Html->css('chosen.min');
echo $this->Html->script('chosen.jquery.min');
echo $this->Html->script('restClient');
?>

View File

@ -1,84 +1,16 @@
<div class="popover_choice select_tag">
<legend><?php echo __('Select Tag');?></legend>
<div style="display:none;">
<?php
if ($scope === 'attribute') {
echo $this->Form->create('Attribute', array('url' => '/attributes/addTag/' . $object_id, 'style' => 'margin:0px;'));
} elseif ($scope === 'event') {
echo $this->Form->create('Event', array('url' => '/events/addTag/' . $object_id, 'style' => 'margin:0px;'));
} elseif ($scope === 'tag_collection') {
echo $this->Form->create('TagCollection', array('url' => '/tag_collections/addTag/' . $object_id, 'style' => 'margin:0px;'));
}
echo $this->Form->input('attribute_ids', array('style' => 'display:none;', 'label' => false));
echo $this->Form->input('tag', array('value' => 0));
echo $this->Form->end();
?>
</div>
<div style="text-align:right;width:100%;" class="select_tag_search">
<input id="filterField" style="width:100%;border:0px;padding:0px;" value="<?php echo h($filterData); ?>" placeholder="<?php echo __('search tags…');?>"/>
</div>
<div class="popover_choice_main" id ="popover_choice_main">
<table style="width:100%;">
<div style="display:none;">
<?php
foreach ($options as $k => &$option):
$choice_id = $k;
if ($taxonomy_id === 'collections') {
$choice_id = 'collection_' . $choice_id;
}
if ($scope === 'attribute') {
echo $this->Form->create('Attribute', array('url' => '/attributes/addTag/' . $object_id, 'style' => 'margin:0px;'));
} elseif ($scope === 'event') {
echo $this->Form->create('Event', array('url' => '/events/addTag/' . $object_id, 'style' => 'margin:0px;'));
} elseif ($scope === 'tag_collection') {
echo $this->Form->create('TagCollection', array('url' => '/tag_collections/addTag/' . $object_id, 'style' => 'margin:0px;'));
}
echo $this->Form->input('attribute_ids', array('style' => 'display:none;', 'label' => false));
echo $this->Form->input('tag', array('value' => 0));
echo $this->Form->end();
?>
<tr style="border-top:1px solid black;" class="templateChoiceButton shown" id="field_<?php echo h($choice_id); ?>">
<?php
$onClickForm = 'quickSubmitTagForm';
if ($scope === 'attribute') {
$onClickForm = 'quickSubmitAttributeTagForm';
}
if ($scope === 'tag_collection') {
$onClickForm = 'quickSubmitTagCollectionTagForm';
}
echo '<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="' . $onClickForm .
'(\'' . h($object_id) . '\', \'' . h($choice_id) . '\');" title="' . h($expanded[$k]) . '" role="button" tabindex="0" aria-label="' .
__('Attach tag') . ' ' . h($option) . '">' . h($option) . '</td>';
?>
</tr>
<?php endforeach; ?>
</table>
</div>
<div role="button" tabindex="0" aria-label="<?php echo __('Return to taxonomy selection');?>" class="popover-back useCursorPointer" onClick="getPopup('<?php echo h($object_id) . '/' . h($scope); ?>', 'tags', 'selectTaxonomy');" title="<?php echo __('Select Taxonomy');?>"><?php echo __('Back to Taxonomy Selection');?></div>
<div role="button" tabindex="0" aria-label="<?php echo __('Cancel');?>" class="templateChoiceButton templateChoiceButtonLast" onClick="cancelPopoverForm();"><?php echo __('Cancel');?></div>
</div>
<script type="text/javascript">
var tags = <?php echo json_encode($options); ?>;
$(document).ready(function() {
resizePopoverBody();
// Places the cursor at the end of the input before focusing
var filterField = $("#filterField");
var tempValue = filterField.val();
filterField.val('');
filterField.val(tempValue);
filter();
filterField.focus();
});
function filter() {
var filterString = $("#filterField").val().toLowerCase();
$.each(tags, function(index, value) {
if (value.toLowerCase().indexOf(filterString) == -1) {
let element = $('#field_' + index);
element.hide();
element.removeClass('shown');
} else {
let element = $('#field_' + index);
element.show();
element.addClass('shown');
}
});
}
$('#filterField').keyup(filter);
$(window).resize(function() {
resizePopoverBody();
});
</script>
<?php echo $this->Html->script('tag-selection-keyboard-navigation.js'); ?>
<?php echo $this->element('generic_picker'); ?>

View File

@ -1,96 +0,0 @@
<div class="popover_choice select_tag_source">
<legend><?php echo __('Select Tag Source');?></legend>
<div style="text-align:right;width:100%;" class="select_tag_search">
<input id="filterField" style="width:100%;border:0px;padding:0px;" placeholder="<?php echo __('search tags…');?>"/>
</div>
<div class="popover_choice_main" id ="popover_choice_main">
<table style="width:100%;">
<?php
if ($favourites) {
echo sprintf(
'<tr style="border-bottom:1px solid black;" class="templateChoiceButton">%s</tr>',
sprintf(
'<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%%;" onClick="getPopup(\'%s/favourites/%s\', \'tags\', \'selectTag\');">%s</td>',
h($object_id),
h($scope),
__('Favourite Tags')
)
);
}
if ($scope !== 'tag_collection') {
echo sprintf(
'<tr style="border-bottom:1px solid black;" class="templateChoiceButton">%s</tr>',
sprintf(
'<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%%;" onClick="getPopup(\'%s/collections/%s\', \'tags\', \'selectTag\');">%s</td>',
h($object_id),
h($scope),
__('Tag Collections')
)
);
}
echo sprintf(
'<tr style="border-bottom:1px solid black;" class="templateChoiceButton">%s</tr>',
sprintf(
'<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%%;" onClick="getPopup(\'%s/0/%s\', \'tags\', \'selectTag\');">%s</td>',
h($object_id),
h($scope),
__('Custom Tags')
)
);
echo sprintf(
'<tr style="border-bottom:1px solid black;" class="templateChoiceButton">%s</tr>',
sprintf(
'<td id="allTags" style="padding-left:10px;padding-right:10px; text-align:center;width:100%%;" data-url="%s/all/%s" onClick="getPopup(this.getAttribute(\'data-url\') + $(\'#filterField\').val(), \'tags\', \'selectTag\');">%s</td>',
h($object_id),
h($scope),
__('All Tags')
)
);
foreach ($options as $k => &$option) {
echo sprintf(
'<tr style="border-bottom:1px solid black;" class="templateChoiceButton">%s</tr>',
sprintf(
'<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%%;" onClick="getPopup(\'%s/%s/%s\', \'tags\', \'selectTag\');">%s: %s</td>',
h($object_id),
h($k),
h($scope),
__('Taxonomy Library'),
h($option)
)
);
}
?>
</table>
</div>
<div class="templateChoiceButton templateChoiceButtonLast" onClick="cancelPopoverForm();"><?php echo __('Cancel');?></div>
</div>
<script type="text/javascript">
$(document).ready(function() {
resizePopoverBody();
try {
new Promise(function(resolve) { setTimeout(function() {$("#filterField").focus()}, 100)});
} catch(error) {
setTimeout(function() {$("#filterField").focus()}, 100);
}
});
$(window).resize(function() {
resizePopoverBody();
});
var lastKeyPressTimestamp = null;
function onKeyUp() {
lastKeyPressTimestamp = (new Date()).getTime();
setTimeout(function() {
if(lastKeyPressTimestamp + 400 < (new Date()).getTime()) {
var filterString = $("#filterField").val().toLowerCase();
if(filterString.length > 0) {
$('#allTags').click();
}
}
}, 500);
}
$('#filterField').keyup(onKeyUp);
</script>

View File

@ -111,7 +111,7 @@ foreach ($list as $k => $item): ?>
&nbsp;
</td>
<td class="shortish"><?php echo h($item['Tag']['count']); ?>&nbsp;</td>
<td class="shortish"><a href="<?php echo $baseurl . "/attributes/search/attributetag:" . $item['Tag']['id']; ?>"><?php echo h($item['Tag']['attribute_count']); ?></a> </td>
<td class="shortish"><a href="<?php echo $baseurl . "/attributes/search/tags:" . $item['Tag']['id']; ?>"><?php echo h($item['Tag']['attribute_count']); ?></a> </td>
<td class="shortish">
<?php echo $this->element('sparkline', array('id' => $item['Tag']['id'], 'csv' => isset($csv[$k]) ? $csv[$k] : $emptyDate)); ?>
</td>

View File

@ -103,7 +103,7 @@
<?php
if ($item['existing_tag']):
?>
<a href='<?php echo $baseurl."/attributes/search/attributetag:". h($item['existing_tag']['Tag']['id']);?>'><?php echo count($item['existing_tag']['AttributeTag']);?></a>
<a href='<?php echo $baseurl."/attributes/search/tags:". h($item['existing_tag']['Tag']['id']);?>'><?php echo count($item['existing_tag']['AttributeTag']);?></a>
<?php
else:
echo __('N/A');

@ -1 +1 @@
Subproject commit 96c9c146052f6cd52577721cdbdcf005e11bf6ae
Subproject commit 1f9f6d951fb7d9dd3c2ad7dc43f87a572d4f473b

@ -1 +1 @@
Subproject commit d45b46c8d22de3e9e070c473619cb1e5f25ba368
Subproject commit 3320d14b68f78d8ca4c40a0a8f0af114f224a742

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 B

View File

@ -894,6 +894,69 @@ a.proposal_link_red:hover {
padding-left:10px;
}
a.pill-pre-picker {
background-color: #fcfcfc;
font-weight: bold;
border: 1px #65737ec8 solid;
}
.nav-pills > .active > a.pill-pre-picker {
background-color: #65737e32;
color: #000;
}
.generic_picker {
display: inline-block;
min-width: 500px;
}
.generic_picker ul.nav {
margin-bottom: 0px;
}
.generic-picker-wrapper {
padding: 7px;
margin-top: 3px;
background-color: #65737e32;
border: 1px #65737ec8 solid;
border-radius: 7px;
}
.generic-picker-wrapper:before {
content: '';
margin-right: 5px;
margin-left: 2px;
border-left: 1px solid;
border-bottom: 1px solid;
height: 10px;
width: 5px;
display: inline-block;
float: left;
}
.active-result .fa:before {
margin-right: 5px;
}
.chosen-container .chosen-results li {
overflow: auto;
}
/* hacky hack: center selected item info icon */
.chosen-container-single span it.fa, .chosen-single-with-deselect span it.fa {
line-height: 24px;
margin-right: 8px;
}
.apply_css_arrow:before {
content: '';
margin-right: 5px;
margin-left: 2px;
border-left: 1px solid;
border-bottom: 1px solid;
height: 10px;
width: 5px;
display: inline-block;
float: left;
}
.gray_out {
display:none;
width: 100%;

View File

@ -5,6 +5,10 @@
var typeaheadDataMatrixSearch;
var pickedGalaxies = [];
var chosen_options = {
width: '100%',
};
$(document).ready(function() {
$('#attack-matrix-tabscontroller span').off('click.tab').on('click.tab', function (e) {
@ -16,7 +20,7 @@
var colNum = $(jfilter+' .matrix-table > thead > tr > th :visible').length;
$('#popover_form_large').css('min-width', 100*colNum);
adapt_position_from_viewport(100*colNum);
})
});
// form
$('.ajax_popover_form .cell-picking').off('click.picking').on('click.picking', function() {
@ -42,8 +46,8 @@
// trigger contextual menu
var target = event.target.getBoundingClientRect();
var parentDom = document.getElementById('matrix_container').getBoundingClientRect();
var x = target.width/2 - 30;
var y = target.height/2 - 14;
var x = target.width/2 - 30;
var y = target.height/2 - 14;
matrixContextualMenu(event.target, x, y, tagName, tagId, [
'Tag event',
'Filter event',
@ -69,14 +73,25 @@
});
scoredCells.hover(function() { enteringScoredCell($(this), '.statistics_attack_matrix'); }, function() { leavingScoredCell('.statistics_attack_matrix'); });
$('.statistics_attack_matrix #checkbox_attackMatrix_showAll').off('click.showAll').on('click.showAll', function() { toggleAttackMatrixCells('.statistics_attack_matrix'); });
// resize
$('span[data-toggle="tab"]').off('shown.resize').on('shown.resize', function (e) {
var tabId = $(e.target).attr('href');
resizeHeader(tabId);
});
$('#attack-matrix-chosen-select').chosen(chosen_options).on('change', function(event, selected) {
if (selected !== undefined) {
var clusterId = selected.selected;
clusterId = clusterId === undefined ? selected.deselected : clusterId;
if (clusterId !== undefined) {
var $option = $('td[data-cluster-id="' + clusterId + '"]');
pickCell($option, clusterId, false);
}
}
});
});
function resizeHeader(tabId) {
if (tabId === undefined) {
tabId = '';
@ -112,10 +127,10 @@
visibilityVal = 'hidden';
displayVal = 'none';
}
$(jfilter+' .heatCell').filter(function() {
return $(this).attr('data-score') == 0;
}).css({
}).css({
visibility: visibilityVal,
});
var rowNum = $(jfilter+' .matrix-table > tbody > tr').length;
@ -130,7 +145,7 @@
$(jfilter+' .matrix-table > tbody > tr:nth-child('+i+')').css({ display: displayVal });
}
}
// hide empty column
for (var i=1; i<=colNum; i++) {
var cellNoValues = $(jfilter+' .matrix-table tr td:nth-child('+i+')').filter(function() {
@ -142,16 +157,16 @@
}
}
}
function enteringScoredCell(elem, jfilter) {
var score = elem.attr('data-score');
adjust_caret_on_scale(score, jfilter);
}
function leavingScoredCell(jfilter) {
adjust_caret_on_scale(0, jfilter);
}
function adjust_caret_on_scale(score, jfilter) {
var totWidth = $(jfilter + ' #matrix-heatmap-legend').width();
var maxScore = parseInt($(jfilter + ' #matrix-heatmap-maxval').text());
@ -188,7 +203,7 @@
div = document.createElement('div');
div.id = 'matrixContextualMenu';
cell.appendChild(div);
div = $(div);
div.empty();
div.css('position', 'absolute');
@ -201,7 +216,7 @@
switch(func_name[i]) {
case 'Tag event':
span.addClass('fa fa-tag');
span.click(function(evt) {
span.click(function(evt) {
if(confirm('Are you sure you want to attach ' + tagName + ' to this event?')) {
makeTagging([tagId]);
}
@ -210,7 +225,7 @@
break;
case 'Filter event':
span.addClass('fa fa-filter');
span.click(function(evt) {
span.click(function(evt) {
filterEvent(tagName, tagId);
div.remove();
});
@ -221,14 +236,14 @@
} else {
span.addClass('fa fa-check');
}
span.click(function(evt) {
span.click(function(evt) {
pickCell($(cell), tagId);
div.remove();
});
break;
default:
span.addClass('fa fa-filter');
span.click(function(evt) {
span.click(function(evt) {
filterEvent(tagName, tagId);
div.remove();
});
@ -258,16 +273,25 @@
filterAttributes('value', $('#attributesFilterField').data('eventid'));
}
function pickCell(cell, tagId) {
function pickCell(cell, clusterId, recurseChosen) {
recurseChosen = recurseChosen === undefined ? true : recurseChosen;
clusterId = parseInt(clusterId);
var $cells = $('td[data-cluster-id="' + clusterId + '"]');
if (!cell.hasClass('cell-picked')) {
pickedGalaxies.push(tagId);
cell.addClass('cell-picked');
pickedGalaxies.push(clusterId);
$cells.addClass('cell-picked');
} else { // remove class and data from array
var i = pickedGalaxies.indexOf(tagId);
var i = pickedGalaxies.indexOf(clusterId);
if (i > -1) {
pickedGalaxies.splice(i, 1);
}
cell.removeClass('cell-picked');
$cells.removeClass('cell-picked');
}
var $select = $('#attack-matrix-chosen-select');
if (recurseChosen) {
$select.val(pickedGalaxies).trigger('chosen:updated');
}
if (pickedGalaxies.length > 0) {

File diff suppressed because one or more lines are too long

View File

@ -61,6 +61,7 @@ function fetchAddSightingForm(id, onvalue) {
function publishPopup(id, type) {
var action = "alert";
if (type == "publish") action = "publish";
if (type == "unpublish") action = "unpublish";
var destination = 'attributes';
$.get( "/events/" + action + "/" + id, function(data) {
$("#confirmation_box").html(data);
@ -109,6 +110,7 @@ function cancelPrompt(isolated) {
}
$("#confirmation_box").fadeOut();
$("#confirmation_box").empty();
$('.have-a-popover').popover('destroy');
}
function submitDeletion(context_id, action, type, id) {
@ -558,8 +560,9 @@ function submitForm(type, id, field, context) {
return false;
};
function quickSubmitTagForm(event_id, tag_id) {
$('#EventTag').val(tag_id);
function quickSubmitTagForm(selected_tag_ids, addData) {
var event_id = addData.id;
$('#EventTag').val(JSON.stringify(selected_tag_ids));
$.ajax({
data: $('#EventSelectTagForm').closest("form").serialize(),
beforeSend: function (XMLHttpRequest) {
@ -586,8 +589,9 @@ function quickSubmitTagForm(event_id, tag_id) {
return false;
}
function quickSubmitAttributeTagForm(attribute_id, tag_id) {
$('#AttributeTag').val(tag_id);
function quickSubmitAttributeTagForm(selected_tag_ids, addData) {
var attribute_id = addData.id;
$('#AttributeTag').val(JSON.stringify(selected_tag_ids));
if (attribute_id == 'selected') {
$('#AttributeAttributeIds').val(getSelected());
}
@ -621,8 +625,9 @@ function quickSubmitAttributeTagForm(attribute_id, tag_id) {
return false;
}
function quickSubmitTagCollectionTagForm(tag_collection_id, tag_id) {
$('#TagCollectionTag').val(tag_id);
function quickSubmitTagCollectionTagForm(selected_tag_ids, addData) {
var tag_collection_id = addData.id;
$('#TagCollectionTag').val(JSON.stringify(selected_tag_ids));
$.ajax({
data: $('#TagCollectionSelectTagForm').closest("form").serialize(),
beforeSend: function (XMLHttpRequest) {
@ -691,6 +696,12 @@ function handleGenericAjaxResponse(data, skip_reload) {
} else {
responseArray = data;
}
// remove remaining popovers
cancelPrompt();
// in case the origin node has been deleted (e.g. tags)
$('.popover').remove();
if (responseArray.saved) {
showMessage('success', responseArray.success);
if (responseArray.hasOwnProperty('check_publish')) {
@ -838,7 +849,8 @@ function multiSelectAction(event, context) {
}
function editSelectedAttributes(event) {
simplePopup("/attributes/editSelected/" + event);
var selectedAttributeIds = getSelected();
simplePopup("/attributes/editSelected/" + event + "/" + selectedAttributeIds);
}
function addSelectedTaxonomies(taxonomy) {
@ -953,10 +965,9 @@ function loadAttributeTags(id) {
});
}
function removeObjectTagPopup(context, object, tag) {
function removeObjectTagPopup(clicked, context, object, tag) {
$.get( "/" + context + "s/removeTag/" + object + '/' + tag, function(data) {
$("#confirmation_box").html(data);
openPopup("#confirmation_box");
openPopover(clicked, data);
});
}
@ -989,6 +1000,11 @@ function removeObjectTag(context, object, tag) {
return false;
}
function redirectAddObject(templateId, additionalData) {
var eventId = additionalData['event_id'];
window.location = '/objects/add/' + eventId + '/' + templateId;
}
function clickCreateButton(event, type) {
var destination = 'attributes';
if (type == 'Proposal') destination = 'shadow_attributes';
@ -1391,9 +1407,61 @@ function openPopup(id) {
$(id).fadeIn();
}
function getMitreMatrixPopup(id) {
function openPopover(clicked, data) {
/* popup handling */
var $clicked = $(clicked);
var randomId = Math.random().toString(36).substr(2,9); // used to recover the button that triggered the popover (so that we can destroy the popover)
var loadingHtml = '<div style="height: 75px; width: 75px;"><div class="spinner"></div><div class="loadingText">Loading</div></div>';
$clicked.attr('data-dismissid', randomId);
var closeButtonHtml = '<button type="button" class="close" style="margin-left: 5px;" onclick="$(&apos;[data-dismissid=&quot;' + randomId + '&quot;]&apos;).popover(\'destroy\');">×</button>';
if (!$clicked.data('popover')) {
$clicked.addClass('have-a-popover');
$clicked.popover({
html: true,
trigger: 'manual',
content: loadingHtml,
container: 'body',
template: '<div class="popover" role="tooltip" data-dismissid="' + randomId + '"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"><div class="data-content"></div></div></div>'
})
.on('shown.bs.popover', function(event) {
var $this = $(this);
var title = $this.attr('title');
var popover = $('div.popover[data-dismissid="' + randomId + '"]');
title = title === "" ? $this.attr('data-original-title') : title;
if (title === "") {
title = "&nbsp;";
// adjust popover position (title was empty)
var top = popover.offset().top;
popover.css('top', (top-17) + 'px');
}
var popoverTitle = popover.find('h3.popover-title');
popoverTitle.html(title + closeButtonHtml);
})
.popover('show')
.on('keydown.volatilePopover', function(e) {
if(e.keyCode == 27) { // ESC
$(this).popover('destroy');
$(this).off('keydown.volatilePopover');
}
});
} else {
// $clicked.popover('show');
}
var popover = $clicked.data('popover');
if (data === undefined) {
return popover
} else if (popover.options.content !== data) {
popover.options.content = data;
$clicked.popover('show');
}
}
function getMitreMatrixPopup(scope_id, scope) {
cancelPopoverForm();
getPopup(scope_id + '/' + id, 'events', 'viewMitreAttackMatrix', '', '#popover_form_large');
getPopup(scope + '/' + scope_id, 'events', 'viewMitreAttackMatrix', '', '#popover_form_large');
}
function getPopup(id, context, target, admin, popupType) {
@ -1427,6 +1495,67 @@ function getPopup(id, context, target, admin, popupType) {
});
}
// Same as getPopup function but create a popover to populate first
function popoverPopup(clicked, id, context, target, admin) {
var url = "";
if (typeof admin !== 'undefined' && admin != '') url+= "/admin";
if (context != '') {
url += "/" + context;
}
if (target != '') url += "/" + target;
if (id != '') url += "/" + id;
var popover = openPopover(clicked, undefined);
$clicked = $(clicked);
// actual request //
$.ajax({
dataType:"html",
async: true,
cache: false,
success:function (data, textStatus) {
if (popover.options.content !== data) {
popover.options.content = data;
$clicked.popover('show');
}
},
error:function() {
popover.options.content = '<div class="alert alert-error" style="margin-bottom: 0px;">Something went wrong - the queried function returned an exception. Contact your administrator for further details (the exception has been logged).</div>';
$clicked.popover('show');
},
url: url
});
}
// create a confirm popover on the clicked html node.
function popoverConfirm(clicked) {
var $clicked = $(clicked);
var popoverContent = '<div>';
popoverContent += '<button id="popoverConfirmOK" class="btn btn-primary" onclick=submitPopover(this)>Yes</button>';
popoverContent += '<button class="btn btn-inverse" style="float: right;" onclick=cancelPrompt()>Cancel</button>';
popoverContent += '</div>';
openPopover($clicked, popoverContent);
$("#popoverConfirmOK")
.focus()
.bind("keydown", function(e) {
if (e.ctrlKey && (e.keyCode == 13 || e.keyCode == 10)) {
$(this).click();
}
if(e.keyCode == 27) { // ESC
$clicked.popover('destroy');
}
});
}
function submitPopover(clicked) {
var $clicked = $(clicked);
var $form = $clicked.closest('form');
if ($form.length === 0) { // popover container is body, submit from original node
var dismissid = $clicked.closest('div.popover').attr('data-dismissid');
$form = $('[data-dismissid="' + dismissid + '"]').closest('form');
}
$form.submit();
}
function simplePopup(url) {
$("#gray_out").fadeIn();
$.ajax({
@ -3292,23 +3421,36 @@ $('.galaxy-toggle-button').click(function() {
function addGalaxyListener(id) {
var target_type = $(id).data('target-type');
var target_id = $(id).data('target-id');
getPopup(target_type + '/' + target_id, 'galaxies', 'selectGalaxyNamespace');
popoverPopup(id, target_id + '/' + target_type, 'galaxies', 'selectGalaxyNamespace');
}
function quickSubmitGalaxyForm(scope, cluster_id, event_id) {
$('#GalaxyTargetId').val(cluster_id);
function quickSubmitGalaxyForm(cluster_ids, additionalData) {
var target_id = additionalData['target_id'];
var scope = additionalData['target_type'];
$('#GalaxyTargetIds').val(JSON.stringify(cluster_ids));
if (target_id == 'selected') {
$('#AttributeAttributeIds').val(getSelected());
}
$.ajax({
data: $('#GalaxySelectClusterForm').closest("form").serialize(),
beforeSend: function (XMLHttpRequest) {
$(".loading").show();
},
success:function (data, textStatus) {
loadGalaxies(event_id, scope);
handleGenericAjaxResponse(data);
if (target_id === 'selected') {
location.reload();
} else {
if (scope == 'tag_collection') {
location.reload();
} else {
loadGalaxies(target_id, scope);
handleGenericAjaxResponse(data);
}
}
},
error:function() {
showMessage('fail', 'Could not add cluster.');
loadGalaxies(event_id, scope);
loadGalaxies(target_id, scope);
},
complete:function() {
$("#popover_form").fadeOut();
@ -3316,7 +3458,7 @@ function quickSubmitGalaxyForm(scope, cluster_id, event_id) {
$(".loading").hide();
},
type:"post",
url: "/galaxies/attachCluster/" + event_id + "/" + scope
url: "/galaxies/attachMultipleClusters/" + target_id + "/" + scope
});
return false;
}

View File

@ -4,8 +4,8 @@
### 0/ MISP Ubuntu 18.04-server install - status
-------------------------
!!! notice
Tested working by @SteveClement on 20181120 (works with **Ubuntu 18.10** too)
As of 20181120 on **Ubuntu 19.04** you need to use Python 3.6 as LIEF with 3.7 is not "eggED" yet.
Tested working by @SteveClement on 20190118 (works with **Ubuntu 18.10** too)
As of 20190118 on **Ubuntu 19.04** you need to use Python 3.6 as LIEF with 3.7 is not "eggED" yet.
You will need to **sudo apt install python3.6-dev** to make everything work according to this guide.
{!generic/community.md!}
@ -38,6 +38,7 @@ sudo apt-get upgrade
```bash
sudo apt-get install postfix -y
```
!!! notice
Postfix Configuration: Satellite system<br />
change the relay server later with:
@ -55,7 +56,7 @@ Once the system is installed you can perform the following steps.
# sudo add-apt-repository universe
# Install the dependencies: (some might already be installed)
sudo apt-get install curl gcc git gnupg-agent make python python3 openssl redis-server sudo vim zip virtualenv -y
sudo apt-get install curl gcc git gpg-agent make python python3 openssl redis-server sudo vim zip virtualenv -y
# Install MariaDB (a MySQL fork/alternative)
sudo apt-get install mariadb-client mariadb-server -y
@ -68,7 +69,7 @@ pw="Password1234"
expect -f - <<-EOF
set timeout 10
spawn sudo mysql_secure_installation
spawn sudo -k mysql_secure_installation
expect "*?assword*"
send -- "$pw\r"
expect "Enter current password for root (enter for none):"
@ -125,7 +126,7 @@ sudo -u www-data git submodule foreach --recursive git config core.filemode fals
sudo -u www-data git config core.filemode false
# Create a python3 virtualenv
sudo apt-get install python3-pip
sudo apt-get install python3-pip -y
pip3 install virtualenv
sudo -u www-data virtualenv -p python3.6 ${PATH_TO_MISP}/venv
@ -148,7 +149,7 @@ sudo -H -u www-data ${PATH_TO_MISP}/venv/bin/pip install .
cd ${PATH_TO_MISP}/app/files/scripts/python-stix
sudo -H -u www-data ${PATH_TO_MISP}/venv/bin/pip install .
cd $PATH_TO_MISP/app/files/scripts/python-maec
sudo -u www-data ${PATH_TO_MISP}/venv/bin/pip install .
sudo -H -u www-data ${PATH_TO_MISP}/venv/bin/pip install .
# install STIX2.0 library to support STIX 2.0 export:
cd ${PATH_TO_MISP}/cti-python-stix2
sudo -H -u www-data ${PATH_TO_MISP}/venv/bin/pip install .
@ -192,11 +193,12 @@ sudo chown -R www-data:www-data ${PATH_TO_MISP}
sudo chmod -R 750 ${PATH_TO_MISP}
sudo chmod -R g+ws ${PATH_TO_MISP}/app/tmp
sudo chmod -R g+ws ${PATH_TO_MISP}/app/files
sudo chmod -R g+ws ${PATH_TO_MISP}/app/files/scripts/tmp
```
### 6/ Create a database and user
-----------------------------
#### Manual procedure:
```bash
# Enter the mysql shell
sudo mysql -u root -p
@ -210,7 +212,7 @@ MariaDB [(none)]> flush privileges;
MariaDB [(none)]> exit
```
#### copy/paste:
#### Same as Manual but for copy/paste foo:
```bash
sudo mysql -u $DBUSER_ADMIN -p$DBPASSWORD_ADMIN -e "create database $DBNAME;"
sudo mysql -u $DBUSER_ADMIN -p$DBPASSWORD_ADMIN -e "grant usage on *.* to $DBNAME@localhost identified by '$DBPASSWORD_MISP';"
@ -228,11 +230,6 @@ sudo -u www-data cat $PATH_TO_MISP/INSTALL/MYSQL.sql | mysql -u $DBUSER_MISP -p$
-----------------------
Now configure your Apache webserver with the DocumentRoot ${PATH_TO_MISP}/app/webroot/
#### Apache version 2.2 config:
```bash
sudo cp ${PATH_TO_MISP}/INSTALL/apache.22.misp.ssl /etc/apache2/sites-available/misp-ssl.conf
```
#### Apache version 2.4 config:
```bash
sudo cp ${PATH_TO_MISP}/INSTALL/apache.24.misp.ssl /etc/apache2/sites-available/misp-ssl.conf
@ -411,7 +408,7 @@ sudo sed -i -e '$i \sudo -u www-data ${PATH_TO_MISP}/venv/bin/misp-modules -l 12
sudo -u www-data bash $PATH_TO_MISP/app/Console/worker/start.sh
# some misp-modules dependencies
sudo apt-get install -y libpq5 libjpeg-dev libfuzzy-dev
sudo apt-get install libpq5 libjpeg-dev libfuzzy-dev -y
sudo chmod 2775 /usr/local/src
sudo chown root:staff /usr/local/src

View File

@ -1,7 +1,7 @@
!!! warning
If you have installed the recommended Python 3 virtualenv to the recommended place of **${PATH_TO_MISP}/venv** set the following MISP configurable
```bash
sudo $CAKE Admin setSetting "MISP.python_bin" "${PATH_TO_MISP}/venv/bin/python"
sudo -H -u www-data $CAKE Admin setSetting "MISP.python_bin" "${PATH_TO_MISP}/venv/bin/python"
```
or on CentOS
```bash

View File

@ -3,152 +3,154 @@
# Default Cake path
export CAKE="$PATH_TO_MISP/app/Console/cake"
# Initialize user and fetch Auth Key
sudo -E $CAKE userInit -q
sudo -H -u www-data -E $CAKE userInit -q
AUTH_KEY=$(mysql -u $DBUSER_MISP -p$DBPASSWORD_MISP misp -e "SELECT authkey FROM users;" | tail -1)
# Setup some more MISP default via cake CLI
# Change base url, either with this CLI command or in the UI
sudo $CAKE Baseurl $MISP_BASEURL
sudo -H -u www-data $CAKE Baseurl $MISP_BASEURL
# example: 'baseurl' => 'https://<your.FQDN.here>',
# alternatively, you can leave this field empty if you would like to use relative pathing in MISP
# 'baseurl' => '',
# Tune global time outs
sudo $CAKE Admin setSetting "Session.autoRegenerate" 0
sudo $CAKE Admin setSetting "Session.timeout" 600
sudo $CAKE Admin setSetting "Session.cookie_timeout" 3600
sudo -H -u www-data $CAKE Admin setSetting "Session.autoRegenerate" 0
sudo -H -u www-data $CAKE Admin setSetting "Session.timeout" 600
sudo -H -u www-data $CAKE Admin setSetting "Session.cookie_timeout" 3600
# Enable GnuPG
sudo $CAKE Admin setSetting "GnuPG.email" "admin@admin.test"
sudo $CAKE Admin setSetting "GnuPG.homedir" "$PATH_TO_MISP/.gnupg"
sudo $CAKE Admin setSetting "GnuPG.password" "Password1234"
sudo -H -u www-data $CAKE Admin setSetting "GnuPG.email" "admin@admin.test"
sudo -H -u www-data $CAKE Admin setSetting "GnuPG.homedir" "$PATH_TO_MISP/.gnupg"
sudo -H -u www-data $CAKE Admin setSetting "GnuPG.password" "Password1234"
# Enable Enrichment set better timeouts
sudo $CAKE Admin setSetting "Plugin.Enrichment_services_enable" true
sudo $CAKE Admin setSetting "Plugin.Enrichment_hover_enable" true
sudo $CAKE Admin setSetting "Plugin.Enrichment_timeout" 300
sudo $CAKE Admin setSetting "Plugin.Enrichment_hover_timeout" 150
sudo $CAKE Admin setSetting "Plugin.Enrichment_cve_enabled" true
sudo $CAKE Admin setSetting "Plugin.Enrichment_dns_enabled" true
sudo $CAKE Admin setSetting "Plugin.Enrichment_services_url" "http://127.0.0.1"
sudo $CAKE Admin setSetting "Plugin.Enrichment_services_port" 6666
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Enrichment_services_enable" true
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Enrichment_hover_enable" true
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Enrichment_timeout" 300
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Enrichment_hover_timeout" 150
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Enrichment_cve_enabled" true
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Enrichment_dns_enabled" true
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Enrichment_services_url" "http://127.0.0.1"
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Enrichment_services_port" 6666
# Enable Import modules set better timout
sudo $CAKE Admin setSetting "Plugin.Import_services_enable" true
sudo $CAKE Admin setSetting "Plugin.Import_services_url" "http://127.0.0.1"
sudo $CAKE Admin setSetting "Plugin.Import_services_port" 6666
sudo $CAKE Admin setSetting "Plugin.Import_timeout" 300
sudo $CAKE Admin setSetting "Plugin.Import_ocr_enabled" true
sudo $CAKE Admin setSetting "Plugin.Import_csvimport_enabled" true
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Import_services_enable" true
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Import_services_url" "http://127.0.0.1"
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Import_services_port" 6666
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Import_timeout" 300
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Import_ocr_enabled" true
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Import_csvimport_enabled" true
# Enable Export modules set better timout
sudo $CAKE Admin setSetting "Plugin.Export_services_enable" true
sudo $CAKE Admin setSetting "Plugin.Export_services_url" "http://127.0.0.1"
sudo $CAKE Admin setSetting "Plugin.Export_services_port" 6666
sudo $CAKE Admin setSetting "Plugin.Export_timeout" 300
sudo $CAKE Admin setSetting "Plugin.Export_pdfexport_enabled" true
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Export_services_enable" true
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Export_services_url" "http://127.0.0.1"
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Export_services_port" 6666
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Export_timeout" 300
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Export_pdfexport_enabled" true
# Enable installer org and tune some configurables
sudo $CAKE Admin setSetting "MISP.host_org_id" 1
sudo $CAKE Admin setSetting "MISP.email" "info@admin.test"
sudo $CAKE Admin setSetting "MISP.disable_emailing" true
sudo $CAKE Admin setSetting "MISP.contact" "info@admin.test"
sudo $CAKE Admin setSetting "MISP.disablerestalert" true
sudo $CAKE Admin setSetting "MISP.showCorrelationsOnIndex" true
sudo -H -u www-data $CAKE Admin setSetting "MISP.host_org_id" 1
sudo -H -u www-data $CAKE Admin setSetting "MISP.email" "info@admin.test"
sudo -H -u www-data $CAKE Admin setSetting "MISP.disable_emailing" true
sudo -H -u www-data $CAKE Admin setSetting "MISP.contact" "info@admin.test"
sudo -H -u www-data $CAKE Admin setSetting "MISP.disablerestalert" true
sudo -H -u www-data $CAKE Admin setSetting "MISP.showCorrelationsOnIndex" true
sudo -H -u www-data $CAKE Admin setSetting "MISP.default_event_tag_collection" 0
# Provisional Cortex tunes
sudo $CAKE Admin setSetting "Plugin.Cortex_services_enable" false
sudo $CAKE Admin setSetting "Plugin.Cortex_services_url" "http://127.0.0.1"
sudo $CAKE Admin setSetting "Plugin.Cortex_services_port" 9000
sudo $CAKE Admin setSetting "Plugin.Cortex_timeout" 120
sudo $CAKE Admin setSetting "Plugin.Cortex_services_url" "http://127.0.0.1"
sudo $CAKE Admin setSetting "Plugin.Cortex_services_port" 9000
sudo $CAKE Admin setSetting "Plugin.Cortex_services_timeout" 120
sudo $CAKE Admin setSetting "Plugin.Cortex_services_authkey" ""
sudo $CAKE Admin setSetting "Plugin.Cortex_ssl_verify_peer" false
sudo $CAKE Admin setSetting "Plugin.Cortex_ssl_verify_host" false
sudo $CAKE Admin setSetting "Plugin.Cortex_ssl_allow_self_signed" true
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Cortex_services_enable" false
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Cortex_services_url" "http://127.0.0.1"
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Cortex_services_port" 9000
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Cortex_timeout" 120
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Cortex_services_url" "http://127.0.0.1"
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Cortex_services_port" 9000
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Cortex_services_timeout" 120
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Cortex_services_authkey" ""
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Cortex_ssl_verify_peer" false
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Cortex_ssl_verify_host" false
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Cortex_ssl_allow_self_signed" true
# Various plugin sightings settings
sudo $CAKE Admin setSetting "Plugin.Sightings_policy" 0
sudo $CAKE Admin setSetting "Plugin.Sightings_anonymise" false
sudo $CAKE Admin setSetting "Plugin.Sightings_range" 365
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Sightings_policy" 0
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Sightings_anonymise" false
sudo -H -u www-data $CAKE Admin setSetting "Plugin.Sightings_range" 365
# Plugin CustomAuth tuneable
sudo $CAKE Admin setSetting "Plugin.CustomAuth_disable_logout" false
sudo -H -u www-data $CAKE Admin setSetting "Plugin.CustomAuth_disable_logout" false
# RPZ Plugin settings
sudo $CAKE Admin setSetting "Plugin.RPZ_policy" "DROP"
sudo $CAKE Admin setSetting "Plugin.RPZ_walled_garden" "127.0.0.1"
sudo $CAKE Admin setSetting "Plugin.RPZ_serial" "\$date00"
sudo $CAKE Admin setSetting "Plugin.RPZ_refresh" "2h"
sudo $CAKE Admin setSetting "Plugin.RPZ_retry" "30m"
sudo $CAKE Admin setSetting "Plugin.RPZ_expiry" "30d"
sudo $CAKE Admin setSetting "Plugin.RPZ_minimum_ttl" "1h"
sudo $CAKE Admin setSetting "Plugin.RPZ_ttl" "1w"
sudo $CAKE Admin setSetting "Plugin.RPZ_ns" "localhost."
sudo $CAKE Admin setSetting "Plugin.RPZ_ns_alt" ""
sudo $CAKE Admin setSetting "Plugin.RPZ_email" "root.localhost"
sudo -H -u www-data $CAKE Admin setSetting "Plugin.RPZ_policy" "DROP"
sudo -H -u www-data $CAKE Admin setSetting "Plugin.RPZ_walled_garden" "127.0.0.1"
sudo -H -u www-data $CAKE Admin setSetting "Plugin.RPZ_serial" "\$date00"
sudo -H -u www-data $CAKE Admin setSetting "Plugin.RPZ_refresh" "2h"
sudo -H -u www-data $CAKE Admin setSetting "Plugin.RPZ_retry" "30m"
sudo -H -u www-data $CAKE Admin setSetting "Plugin.RPZ_expiry" "30d"
sudo -H -u www-data $CAKE Admin setSetting "Plugin.RPZ_minimum_ttl" "1h"
sudo -H -u www-data $CAKE Admin setSetting "Plugin.RPZ_ttl" "1w"
sudo -H -u www-data $CAKE Admin setSetting "Plugin.RPZ_ns" "localhost."
sudo -H -u www-data $CAKE Admin setSetting "Plugin.RPZ_ns_alt" ""
sudo -H -u www-data $CAKE Admin setSetting "Plugin.RPZ_email" "root.localhost"
# Force defaults to make MISP Server Settings less RED
sudo $CAKE Admin setSetting "MISP.language" "eng"
sudo $CAKE Admin setSetting "MISP.proposals_block_attributes" false
sudo -H -u www-data $CAKE Admin setSetting "MISP.language" "eng"
sudo -H -u www-data $CAKE Admin setSetting "MISP.proposals_block_attributes" false
## Redis block
sudo $CAKE Admin setSetting "MISP.redis_host" "127.0.0.1"
sudo $CAKE Admin setSetting "MISP.redis_port" 6379
sudo $CAKE Admin setSetting "MISP.redis_database" 13
sudo $CAKE Admin setSetting "MISP.redis_password" ""
sudo -H -u www-data $CAKE Admin setSetting "MISP.redis_host" "127.0.0.1"
sudo -H -u www-data $CAKE Admin setSetting "MISP.redis_port" 6379
sudo -H -u www-data $CAKE Admin setSetting "MISP.redis_database" 13
sudo -H -u www-data $CAKE Admin setSetting "MISP.redis_password" ""
# Force defaults to make MISP Server Settings less YELLOW
sudo $CAKE Admin setSetting "MISP.ssdeep_correlation_threshold" 40
sudo $CAKE Admin setSetting "MISP.extended_alert_subject" false
sudo $CAKE Admin setSetting "MISP.default_event_threat_level" 4
sudo $CAKE Admin setSetting "MISP.newUserText" "Dear new MISP user,\\n\\nWe would hereby like to welcome you to the \$org MISP community.\\n\\n Use the credentials below to log into MISP at \$misp, where you will be prompted to manually change your password to something of your own choice.\\n\\nUsername: \$username\\nPassword: \$password\\n\\nIf you have any questions, don't hesitate to contact us at: \$contact.\\n\\nBest regards,\\nYour \$org MISP support team"
sudo $CAKE Admin setSetting "MISP.passwordResetText" "Dear MISP user,\\n\\nA password reset has been triggered for your account. Use the below provided temporary password to log into MISP at \$misp, where you will be prompted to manually change your password to something of your own choice.\\n\\nUsername: \$username\\nYour temporary password: \$password\\n\\nIf you have any questions, don't hesitate to contact us at: \$contact.\\n\\nBest regards,\\nYour \$org MISP support team"
sudo $CAKE Admin setSetting "MISP.enableEventBlacklisting" true
sudo $CAKE Admin setSetting "MISP.enableOrgBlacklisting" true
sudo $CAKE Admin setSetting "MISP.log_client_ip" false
sudo $CAKE Admin setSetting "MISP.log_auth" false
sudo $CAKE Admin setSetting "MISP.disableUserSelfManagement" false
sudo $CAKE Admin setSetting "MISP.block_event_alert" false
sudo $CAKE Admin setSetting "MISP.block_event_alert_tag" "no-alerts=\"true\""
sudo $CAKE Admin setSetting "MISP.block_old_event_alert" false
sudo $CAKE Admin setSetting "MISP.block_old_event_alert_age" ""
sudo $CAKE Admin setSetting "MISP.incoming_tags_disabled_by_default" false
sudo $CAKE Admin setSetting "MISP.footermidleft" "This is an initial install"
sudo $CAKE Admin setSetting "MISP.footermidright" "Please configure and harden accordingly"
sudo $CAKE Admin setSetting "MISP.welcome_text_top" "Initial Install, please configure"
sudo $CAKE Admin setSetting "MISP.welcome_text_bottom" "Welcome to MISP, change this message in MISP Settings"
sudo -H -u www-data $CAKE Admin setSetting "MISP.ssdeep_correlation_threshold" 40
sudo -H -u www-data $CAKE Admin setSetting "MISP.extended_alert_subject" false
sudo -H -u www-data $CAKE Admin setSetting "MISP.default_event_threat_level" 4
sudo -H -u www-data $CAKE Admin setSetting "MISP.newUserText" "Dear new MISP user,\\n\\nWe would hereby like to welcome you to the \$org MISP community.\\n\\n Use the credentials below to log into MISP at \$misp, where you will be prompted to manually change your password to something of your own choice.\\n\\nUsername: \$username\\nPassword: \$password\\n\\nIf you have any questions, don't hesitate to contact us at: \$contact.\\n\\nBest regards,\\nYour \$org MISP support team"
sudo -H -u www-data $CAKE Admin setSetting "MISP.passwordResetText" "Dear MISP user,\\n\\nA password reset has been triggered for your account. Use the below provided temporary password to log into MISP at \$misp, where you will be prompted to manually change your password to something of your own choice.\\n\\nUsername: \$username\\nYour temporary password: \$password\\n\\nIf you have any questions, don't hesitate to contact us at: \$contact.\\n\\nBest regards,\\nYour \$org MISP support team"
sudo -H -u www-data $CAKE Admin setSetting "MISP.enableEventBlacklisting" true
sudo -H -u www-data $CAKE Admin setSetting "MISP.enableOrgBlacklisting" true
sudo -H -u www-data $CAKE Admin setSetting "MISP.log_client_ip" false
sudo -H -u www-data $CAKE Admin setSetting "MISP.log_auth" false
sudo -H -u www-data $CAKE Admin setSetting "MISP.disableUserSelfManagement" false
sudo -H -u www-data $CAKE Admin setSetting "MISP.block_event_alert" false
sudo -H -u www-data $CAKE Admin setSetting "MISP.block_event_alert_tag" "no-alerts=\"true\""
sudo -H -u www-data $CAKE Admin setSetting "MISP.block_old_event_alert" false
sudo -H -u www-data $CAKE Admin setSetting "MISP.block_old_event_alert_age" ""
sudo -H -u www-data $CAKE Admin setSetting "MISP.incoming_tags_disabled_by_default" false
sudo -H -u www-data $CAKE Admin setSetting "MISP.footermidleft" "This is an initial install"
sudo -H -u www-data $CAKE Admin setSetting "MISP.footermidright" "Please configure and harden accordingly"
sudo -H -u www-data $CAKE Admin setSetting "MISP.welcome_text_top" "Initial Install, please configure"
sudo -H -u www-data $CAKE Admin setSetting "MISP.welcome_text_bottom" "Welcome to MISP, change this message in MISP Settings"
# Force defaults to make MISP Server Settings less GREEN
sudo $CAKE Admin setSetting "Security.password_policy_length" 12
sudo $CAKE Admin setSetting "Security.password_policy_complexity" '/^((?=.*\d)|(?=.*\W+))(?![\n])(?=.*[A-Z])(?=.*[a-z]).*$|.{16,}/'
sudo -H -u www-data $CAKE Admin setSetting "Security.password_policy_length" 12
sudo -H -u www-data $CAKE Admin setSetting "Security.password_policy_complexity" '/^((?=.*\d)|(?=.*\W+))(?![\n])(?=.*[A-Z])(?=.*[a-z]).*$|.{16,}/'
# Tune global time outs
sudo $CAKE Admin setSetting "Session.autoRegenerate" 0
sudo $CAKE Admin setSetting "Session.timeout" 600
sudo $CAKE Admin setSetting "Session.cookie_timeout" 3600
sudo -H -u www-data $CAKE Admin setSetting "Session.autoRegenerate" 0
sudo -H -u www-data $CAKE Admin setSetting "Session.timeout" 600
sudo -H -u www-data $CAKE Admin setSetting "Session.cookie_timeout" 3600
# Update the galaxies…
sudo $CAKE Admin updateGalaxies
##sudo -H -u www-data $CAKE Admin updateGalaxies
curl --header "Authorization: $AUTH_KEY" --header "Accept: application/json" --header "Content-Type: application/json" -k -X POST https://127.0.0.1/galaxies/update
# Updating the taxonomies…
sudo $CAKE Admin updateTaxonomies
sudo -H -u www-data $CAKE Admin updateTaxonomies
# Updating the warning lists…
##sudo $CAKE Admin updateWarningLists
##sudo -H -u www-data $CAKE Admin updateWarningLists
curl --header "Authorization: $AUTH_KEY" --header "Accept: application/json" --header "Content-Type: application/json" -k -X POST https://127.0.0.1/warninglists/update
# Updating the notice lists…
## sudo $CAKE Admin updateNoticeLists
## sudo -H -u www-data $CAKE Admin updateNoticeLists
curl --header "Authorization: $AUTH_KEY" --header "Accept: application/json" --header "Content-Type: application/json" -k -X POST https://127.0.0.1/noticelists/update
# Updating the object templates…
##sudo $CAKE Admin updateObjectTemplates
##sudo -H -u www-data $CAKE Admin updateObjectTemplates
curl --header "Authorization: $AUTH_KEY" --header "Accept: application/json" --header "Content-Type: application/json" -k -X POST https://127.0.0.1/objectTemplates/update
# Set MISP Live
sudo $CAKE Live $MISP_LIVE
sudo -H -u www-data $CAKE Live $MISP_LIVE
```

View File

@ -10,7 +10,7 @@
```bash
cd /usr/local/src/
sudo apt-get install -y cmake
sudo apt-get install cmake -y
git clone https://github.com/MISP/mail_to_misp.git
git clone https://github.com/stricaud/faup.git
cd faup

View File

@ -8,7 +8,6 @@ sudo -u www-data git clone https://github.com/MISP/misp-dashboard.git
cd misp-dashboard
sudo -H /var/www/misp-dashboard/install_dependencies.sh
sudo sed -i "s/^host\ =\ localhost/host\ =\ 0.0.0.0/g" /var/www/misp-dashboard/config/config.cfg
sudo sed -i -e '$i \sudo -u www-data bash /var/www/misp-dashboard/start_all.sh\n' /etc/rc.local
sudo sed -i '/Listen 80/a Listen 0.0.0.0:8001' /etc/apache2/ports.conf
sudo apt install libapache2-mod-wsgi-py3 -y
@ -57,20 +56,20 @@ sudo systemctl reload apache2
sudo sed -i -e '$i \sudo -u www-data bash /var/www/misp-dashboard/start_all.sh > /tmp/misp-dashboard_rc.local.log\n' /etc/rc.local
# Enable ZeroMQ for misp-dashboard
sudo $CAKE Admin setSetting "Plugin.ZeroMQ_enable" true
sudo $CAKE Admin setSetting "Plugin.ZeroMQ_event_notifications_enable" true
sudo $CAKE Admin setSetting "Plugin.ZeroMQ_object_notifications_enable" true
sudo $CAKE Admin setSetting "Plugin.ZeroMQ_object_reference_notifications_enable" true
sudo $CAKE Admin setSetting "Plugin.ZeroMQ_attribute_notifications_enable" true
sudo $CAKE Admin setSetting "Plugin.ZeroMQ_sighting_notifications_enable" true
sudo $CAKE Admin setSetting "Plugin.ZeroMQ_user_notifications_enable" true
sudo $CAKE Admin setSetting "Plugin.ZeroMQ_organisation_notifications_enable" true
sudo $CAKE Admin setSetting "Plugin.ZeroMQ_port" 50000
sudo $CAKE Admin setSetting "Plugin.ZeroMQ_redis_host" "localhost"
sudo $CAKE Admin setSetting "Plugin.ZeroMQ_redis_port" 6379
sudo $CAKE Admin setSetting "Plugin.ZeroMQ_redis_database" 1
sudo $CAKE Admin setSetting "Plugin.ZeroMQ_redis_namespace" "mispq"
sudo $CAKE Admin setSetting "Plugin.ZeroMQ_include_attachments" false
sudo $CAKE Admin setSetting "Plugin.ZeroMQ_tag_notifications_enable" false
sudo $CAKE Admin setSetting "Plugin.ZeroMQ_audit_notifications_enable" false
sudo -H -u www-data $CAKE Admin setSetting "Plugin.ZeroMQ_enable" true
sudo -H -u www-data $CAKE Admin setSetting "Plugin.ZeroMQ_event_notifications_enable" true
sudo -H -u www-data $CAKE Admin setSetting "Plugin.ZeroMQ_object_notifications_enable" true
sudo -H -u www-data $CAKE Admin setSetting "Plugin.ZeroMQ_object_reference_notifications_enable" true
sudo -H -u www-data $CAKE Admin setSetting "Plugin.ZeroMQ_attribute_notifications_enable" true
sudo -H -u www-data $CAKE Admin setSetting "Plugin.ZeroMQ_sighting_notifications_enable" true
sudo -H -u www-data $CAKE Admin setSetting "Plugin.ZeroMQ_user_notifications_enable" true
sudo -H -u www-data $CAKE Admin setSetting "Plugin.ZeroMQ_organisation_notifications_enable" true
sudo -H -u www-data $CAKE Admin setSetting "Plugin.ZeroMQ_port" 50000
sudo -H -u www-data $CAKE Admin setSetting "Plugin.ZeroMQ_redis_host" "localhost"
sudo -H -u www-data $CAKE Admin setSetting "Plugin.ZeroMQ_redis_port" 6379
sudo -H -u www-data $CAKE Admin setSetting "Plugin.ZeroMQ_redis_database" 1
sudo -H -u www-data $CAKE Admin setSetting "Plugin.ZeroMQ_redis_namespace" "mispq"
sudo -H -u www-data $CAKE Admin setSetting "Plugin.ZeroMQ_include_attachments" false
sudo -H -u www-data $CAKE Admin setSetting "Plugin.ZeroMQ_tag_notifications_enable" false
sudo -H -u www-data $CAKE Admin setSetting "Plugin.ZeroMQ_audit_notifications_enable" false
```

View File

@ -5,7 +5,7 @@ cd /usr/local/src
wget https://github.com/ssdeep-project/ssdeep/releases/download/release-2.14.1/ssdeep-2.14.1.tar.gz
tar zxvf ssdeep-2.14.1.tar.gz
cd ssdeep-2.14.1
./configure
./configure --datadir=/usr --prefix=/usr --localstatedir=/var --sysconfdir=/etc
make
sudo make install

View File

@ -10,7 +10,7 @@
```bash
cd /usr/local/src/
sudo apt-get install -y libssl-dev swig python3-ssdeep p7zip-full unrar-free sqlite python3-pyclamd exiftool radare2 python3-magic python3-sqlalchemy python3-prettytable
sudo apt-get install libssl-dev swig python3-ssdeep p7zip-full unrar-free sqlite python3-pyclamd exiftool radare2 python3-magic python3-sqlalchemy python3-prettytable -y
git clone https://github.com/viper-framework/viper.git
cd viper
virtualenv -p python3.6 venv