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

pull/4408/head
iglocska 2019-04-02 09:28:12 +02:00
commit 084b79e399
17 changed files with 427 additions and 6 deletions

View File

@ -178,6 +178,7 @@ class ACLComponent extends Component
'index' => array('*'),
'previewEvent' => array('*'),
'previewIndex' => array('*'),
'searchCaches' => array('*'),
'toggleSelected' => array('perm_site_admin'),
'view' => array('*'),
),

View File

@ -960,4 +960,50 @@ class FeedsController extends AppController
$this->render('ajax/feedToggleConfirmation');
}
}
public function searchCaches()
{
if (!$this->_isSiteAdmin() && !$this->Auth->user('org_id') == Configure::read('MISP.host_org_id')) {
throw NotAllowedException('You don\'t have access to this feature.');
}
if (isset($this->passedArgs['pages'])) {
$currentPage = $this->passedArgs['pages'];
} else {
$currentPage = 1;
}
$urlparams = '';
App::uses('CustomPaginationTool', 'Tools');
$customPagination = new CustomPaginationTool();
$passedArgs = array();
$hits = array();
$value = false;
if ($this->request->is('post')) {
if (isset($this->request->data['Feed'])) {
$this->request->data = $this->request->data['Feed'];
}
if (isset($this->request->data['value'])) {
$this->request->data = $this->request->data['value'];
}
$value = $this->request->data;
}
if (!empty($this->params['named']['value'])) {
$value = $this->params['named']['value'];
}
$hits = $this->Feed->searchCaches($value);
if ($this->_isRest()) {
return $this->RestResponse->viewData($hits, $this->response->type());
} else {
$this->set('hits', $hits);
}
$params = $customPagination->createPaginationRules($hits, $this->passedArgs, $this->alias);
$this->params->params['paging'] = array('Feed' => $params);
$hits = $customPagination->sortArray($hits, $params, true);
if (is_array($hits)) {
$customPagination->truncateByPagination($hits, $params);
}
$pageCount = count($hits);
$this->set('urlparams', $urlparams);
$this->set('passedArgs', json_encode($passedArgs));
$this->set('passedArgsArray', $passedArgs);
}
}

View File

@ -1502,4 +1502,99 @@ class Feed extends AppModel
}
return $result;
}
public function searchCaches($value)
{
$value = strtolower(trim($value));
$hits = array();
$this->Server = ClassRegistry::init('Server');
$result['Server'] = $this->Server->find('all', array(
'conditions' => array(
'caching_enabled' => 1
),
'recursive' => -1,
'fields' => array('Server.id', 'Server.name', 'Server.url')
));
$redis = $this->setupRedis();
if (empty($value) || $redis->sismember('misp:feed_cache:combined', md5($value))) {
$feeds = $this->find('all', array(
'conditions' => array(
'caching_enabled' => 1
),
'recursive' => -1,
'fields' => array('Feed.id', 'Feed.name', 'Feed.url', 'Feed.source_format')
));
foreach ($feeds as $feed) {
if (empty($value) || $redis->sismember('misp:feed_cache:' . $feed['Feed']['id'], md5($value))) {
if ($feed['Feed']['source_format'] === 'misp') {
$uuid = $redis->smembers('misp:feed_cache:event_uuid_lookup:' . md5($value));
foreach ($uuid as $k => $url) {
$uuid[$k] = explode('/', $url)[1];
}
$feed['Feed']['uuid'] = $uuid;
if (!empty($feed['Feed']['uuid'])) {
foreach ($feed['Feed']['uuid'] as $uuid) {
$feed['Feed']['direct_urls'][] = array(
'url' => sprintf(
'%s/feeds/previewEvent/%s/%s',
Configure::read('MISP.baseurl'),
h($feed['Feed']['id']),
h($uuid)
),
'name' => __('Event %s', $uuid)
);
}
}
$feed['Feed']['type'] = 'MISP Feed';
} else {
$feed['Feed']['type'] = 'Feed';
if (!empty($value)) {
$feed['Feed']['direct_urls'][] = array(
'url' => sprintf(
'%s/feeds/previewIndex/%s',
Configure::read('MISP.baseurl'),
h($feed['Feed']['id'])
),
'name' => __('Feed %s', $feed['Feed']['id'])
);
}
}
$hits[] = $feed;
}
}
}
if (empty($value) || $redis->sismember('misp:server_cache:combined', md5($value))) {
$this->Server = ClassRegistry::init('Server');
$servers = $this->Server->find('all', array(
'conditions' => array(
'caching_enabled' => 1
),
'recursive' => -1,
'fields' => array('Server.id', 'Server.name', 'Server.url')
));
foreach ($servers as $server) {
if (empty($value) || $redis->sismember('misp:server_cache:' . $server['Server']['id'], md5($value))) {
$uuid = $redis->smembers('misp:server_cache:event_uuid_lookup:' . md5($value));
if (!empty($uuid)) {
foreach ($uuid as $k => $url) {
$uuid[$k] = explode('/', $url)[1];
$server['Server']['direct_urls'][] = array(
'url' => sprintf(
'%s/servers/previewEvent/%s/%s',
Configure::read('MISP.baseurl'),
h($server['Server']['id']),
h($uuid[$k])
),
'name' => __('Event %s', h($uuid[$k]))
);
}
}
$server['Server']['uuid'] = $uuid;
$server['Server']['type'] = 'MISP Server';
$hits[] = array('Feed' => $server['Server']);
}
}
}
return $hits;
}
}

View File

@ -0,0 +1,3 @@
<?php
echo h(Hash::extract($row, $field['data_path'])[0]);
?>

View File

@ -0,0 +1,13 @@
<?php
$url_data = Hash::extract($row, $field['data_path']);
$links = array();
foreach ($url_data as $url) {
$links[] = sprintf(
'<a href="%s" title="%s">%s</a>',
h($url['url']),
h($url['name']),
h($url['name'])
);
}
echo implode('<br />', $links);
?>

View File

@ -0,0 +1,20 @@
<?php
$headersHtml = '';
foreach ($fields as $k => $header) {
$header_data = '';
if (!empty($header['sort'])) {
if (!empty($header['name'])) {
$header_data = $paginator->sort($header['sort'], $header['name']);
} else {
$header_data = $paginator->sort($header['sort']);
}
} else {
$header_data = h($header['name']);
}
$headersHtml .= sprintf(
'<th>%s</th>',
$header_data
);
}
echo $headersHtml;
?>

View File

@ -0,0 +1,46 @@
<?php
/*
* echo $this->element('/genericElements/IndexTable/index_table', array(
* 'top_bar' => (
* // search/filter bar information compliant with ListTopBar
* ),
* 'data' => array(
// the actual data to be used
* ),
* 'fields' => array(
* // field list with information for the paginator, the elements used for the individual cells, etc
* ),
* 'title' => optional title,
* 'description' => optional description
* ));
*
*/
if (!empty($data['title'])) {
echo sprintf('<h2>%s</h2>', h($data['title']));
}
if (!empty($data['description'])) {
echo sprintf('<p>%s</p>', h($data['description']));
}
echo $this->element('/genericElements/IndexTable/pagination', array('paginator' => $this->Paginator));
if (!empty($data['top_bar'])) {
echo $this->element('/genericElements/ListTopBar/scaffold', array('data' => $data['top_bar']));
}
$rows = '';
foreach ($data['data'] as $k => $data_row) {
$row_element = 'row';
if (!empty($data['row_element'])) {
$row_element = $data['row_element'];
}
$rows .= sprintf(
'<tr>%s</tr>',
$this->element('/genericElements/IndexTable/' . $row_element, array('k' => $k, 'row' => $data_row, 'fields' => $data['fields']))
);
}
echo sprintf(
'<table class="table table-striped table-hover table-condensed">%s%s</table>',
$this->element('/genericElements/IndexTable/headers', array('fields' => $data['fields'], 'paginator' => $this->Paginator)),
$rows
);
echo $this->element('/genericElements/IndexTable/pagination_counter', array('paginator' => $this->Paginator));
echo $this->element('/genericElements/IndexTable/pagination', array('paginator' => $this->Paginator));
?>

View File

@ -0,0 +1,14 @@
<?php
$paginator->options(array(
'update' => '.span12',
'evalScripts' => true,
'before' => '$(".progress").show()',
'complete' => '$(".progress").hide()',
));
sprintf(
'<div class="pagination"><ul>%s%s%s</ul></div>',
$paginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span')),
$paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span')),
$paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'))
);
?>

View File

@ -0,0 +1,8 @@
<?php
echo sprintf(
'<p>%s</p>',
$paginator->counter(array(
'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')
))
);
?>

View File

@ -0,0 +1,20 @@
<?php
$rowHtml = '';
foreach ($fields as $k => $field) {
if (empty($field['element'])) {
$valueField = $this->element('/genericElements/IndexTable/Fields/generic_field', array('field' => $field, 'row' => $row, 'data_path' => empty($field['data_path']) ? '' : $field['data_path']));
} else {
$valueField = $this->element('/genericElements/IndexTable/Fields/' . $field['element'], array('field' => $field, 'row' => $row, 'data_path' => empty($field['data_path']) ? '' : $field['data_path']));
}
$rowHtml .= sprintf(
'<td%s%s%s%s%s>%s</td>',
(empty($field['id'])) ? '' : sprintf('id="%s"', $field['id']),
(empty($field['class'])) ? '' : sprintf(' class="%s"', $field['class']),
(empty($field['style'])) ? '' : sprintf(' style="%s"', $field['style']),
(empty($field['title'])) ? '' : sprintf(' title="%s"', $field['title']),
(empty($field['ondblclick'])) ? '' : sprintf(' ondblclick="%s"', $field['ondblclick']),
$valueField
);
}
echo ($rowHtml);
?>

View File

@ -1,4 +1,16 @@
<?php
/*
* Run a quick filter against the current API endpoint
* Result is passed via URL parameters, by default using the searchall key
* Valid parameters:
* - data: data-* fields
* - searchKey: data-search-key, specifying the key to be used (defaults to searchall)
* - fa-icon: an icon to use for the lookup $button
* - buttong: Text to use for the lookup button
* - cancel: Button for quickly removing the filters
* - placeholder: optional placeholder for the text field
* - id: element ID for the input field - defaults to quickFilterField
*/
if (!isset($data['requirement']) || $data['requirement']) {
$button = empty($data['button']) && empty($data['fa-icon']) ? '' : sprintf(
'<button class=" btn btn-small btn-inverse" %s id="quickFilterButton">%s%s</button>',
@ -10,10 +22,11 @@
$button .= $this->element('/genericElements/ListTopBar/element_simple', array('data' => $data['cancel']));
}
$input = sprintf(
'<input type="text" class="span3 input-small" placeholder="%s" aria-label="%s" style="padding: 2px 6px;" id="%s">',
'<input type="text" class="span3 input-small" placeholder="%s" aria-label="%s" style="padding: 2px 6px;" id="%s" data-searchkey="%s">',
empty($data['placeholder']) ? '' : h($data['placeholder']),
empty($data['placeholder']) ? '' : h($data['placeholder']),
empty($data['id']) ? 'quickFilterField' : h($data['id'])
empty($data['id']) ? 'quickFilterField' : h($data['id']),
empty($data['searchKey']) ? 'searchall' : h($data['searchKey'])
);
echo sprintf(
'<div class="btn-group pull-right"><div class="input-append" style="margin-bottom:0px;">%s%s</div></div>',

View File

@ -874,6 +874,10 @@
'url' => '/feeds/index',
'text' => __('List Feeds')
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'url' => '/feeds/searchCaches',
'text' => __('Search Feed Caches')
));
if ($isSiteAdmin) {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'url' => '/feeds/add',

View File

@ -221,6 +221,11 @@
'text' => __('List Feeds'),
'url' => '/feeds/index',
'requirement' => ($isSiteAdmin || $hostOrgUser)
),
array(
'text' => __('Search Feed Caches'),
'url' => '/feeds/searchCaches',
'requirement' => ($isSiteAdmin || $hostOrgUser)
)
)
),

View File

@ -36,12 +36,58 @@
<?php
foreach ($event['Object'] as $o => $object) {
?>
<table class="table table-condensed table-stripped">
<table class="MISPObject" style="width:100%;">
<tbody>
<tr>
<td class="bold"><?php echo __('Name');?></td>
<td><?php echo h($object['name']); ?></td>
<td class='ObjectName'><?php echo h($object['name']); ?></td>
</tr>
<tr>
<td class="bold"><?php echo __('UUID');?></td>
<td class='ObjectUUID'><?php echo h($object['uuid']); ?></td>
</tr>
<?php if (isset($object['ObjectReference']) && !empty($object['ObjectReference'])) { ?>
<tr>
<td class="bold"><?php echo __('References:'); ?></td>
</tr>
<table class="table table-condensed" style="margin-bottom:0px;">
<thead>
<th><?php echo __('Referenced name/type'); ?></th>
<th><?php echo __('Referenced uuid'); ?></th>
<th><?php echo __('Relationship'); ?></th>
</thead>
<tbody>
<?php
foreach ($object['ObjectReference'] as $reference) {
echo '<tr class="ObjectReference">';
$referenced_uuid = $reference['referenced_uuid'];
foreach ($event['Object'] as $object_reference) {
if ($referenced_uuid === $object_reference['uuid']) {
$name = $object_reference['name'];
break;
}
}
if (!isset($name)) {
foreach ($event['Attribute'] as $attribute_reference) {
if ($referenced_uuid === $attribute_reference['uuid']) {
$name = $attribute_reference['type'];
break;
}
}
if (!isset($name)) {
$name = '';
}
}
echo '<td class="ReferencedName">' . h($name) . '</td>';
unset($name);
echo '<td class="ReferencedUUID">' . h($referenced_uuid) . '</td>';
echo '<td class="Relationship">' . h($reference['relationship_type']) . '</td>';
echo '</tr>';
}
echo '</tbody>';
echo '</table>';
}
?>
<tr>
<table class="table table-condensed table-striped">
<thead>

View File

@ -266,7 +266,7 @@ foreach ($feeds as $item):
endif;
if ($item['Feed']['caching_enabled'] && $isSiteAdmin):
?>
<a href="<?php echo $baseurl;?>/feeds/cacheFeeds/<?php echo h($item['Feed']['id']); ?>" title="Cache feed"><span class="fa fa-memory"></span></a>
<a href="<?php echo $baseurl;?>/feeds/cacheFeeds/<?php echo h($item['Feed']['id']); ?>" title="Cache feed"><span class="black fa fa-memory"></span></a>
<?php
endif;
?>

View File

@ -0,0 +1,83 @@
<?php
/*
* echo $this->element('/genericElements/IndexTable/index_table', array(
* 'top_bar' => (
* // search/filter bar information compliant with ListTopBar
* ),
* 'data' => array(
// the actual data to be used
* ),
* 'fields' => array(
* // field list with information for the paginator
* ),
* 'title' => optional title,
* 'description' => optional description
* ));
*
*/
echo '<div class="index">';
echo $this->element('/genericElements/IndexTable/index_table', array(
'data' => array(
'data' => $hits,
'top_bar' => array(
'children' => array(
array(
'type' => 'search',
'button' => __('Filter'),
'placeholder' => __('Enter value to search'),
'data' => '',
'searchKey' => 'value'
)
)
),
'fields' => array(
array(
'name' => __('Id'),
'sort' => 'id',
'class' => 'short',
'data_path' => 'Feed.id'
),
array(
'name' => __('Type'),
'class' => 'short',
'sort' => 'type',
'data_path' => 'Feed.type'
),
array(
'name' => __('Name'),
'class' => 'short',
'sort' => 'name',
'data_path' => 'Feed.name'
),
array(
'name' => __('Feed URL'),
'sort' => 'url',
'data_path' => 'Feed.url'
),
array(
'name' => __('Link to correlation'),
'element' => 'links',
'data_path' => 'Feed.direct_urls',
'class' => 'action'
)
),
'title' => __('Feed Cache Search'),
'description' => __('Search for values potentially contained in the cached feeds and servers.')
)
));
echo '</div>';
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'feeds', 'menuItem' => 'searchCaches'));
?>
<script type="text/javascript">
var passedArgsArray = <?php echo $passedArgs; ?>;
$(document).ready(function() {
$('#quickFilterButton').click(function() {
runIndexQuickFilter();
});
$('#quickFilterField').on('keypress', function (e) {
if(e.which === 13) {
runIndexQuickFilter();
}
});
});
</script>

View File

@ -1874,8 +1874,12 @@ function runIndexQuickFilter(preserveParams) {
if (!passedArgsArray) {
var passedArgsArray = [];
}
var searchKey = 'searchall';
if ($('#quickFilterField').data('searchkey')) {
searchKey = $('#quickFilterField').data('searchkey');
}
if ( $('#quickFilterField').val().trim().length > 0){
passedArgsArray["searchall"] = $('#quickFilterField').val().trim();
passedArgsArray[searchKey] = $('#quickFilterField').val().trim();
}
url = here;
if (typeof preserveParams !== "undefined") {