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

pull/5727/head
iglocska 2020-03-25 12:00:22 +01:00
commit a424221c5f
No known key found for this signature in database
GPG Key ID: BEA224F1FEF113AC
33 changed files with 1086 additions and 434 deletions

View File

@ -97,6 +97,7 @@ class DashboardsController extends AppController
$dashboardWidget = $this->Dashboard->loadWidget($this->Auth->user(), $data['widget']);
$data['description'] = empty($dashboardWidget->description) ? '' : $dashboardWidget->description;
$data['params'] = empty($dashboardWidget->params) ? array() : $dashboardWidget->params;
$data['params'] = array_merge($data['params'], array('widget_config' => __('Configuration of the widget that will be passed to the render. Check the view for more information')));
$data['params'] = array_merge(array('alias' => __('Alias to use as the title of the widget')), $data['params']);
}
$this->set('data', $data);
@ -174,9 +175,11 @@ class DashboardsController extends AppController
} else {
$data = json_decode($data, true)['data'];
}
$valueConfig = json_decode($value['config'], true);
$config = array(
'render' => $dashboardWidget->render,
'autoRefreshDelay' => empty($dashboardWidget->autoRefreshDelay) ? false : $dashboardWidget->autoRefreshDelay
'autoRefreshDelay' => empty($dashboardWidget->autoRefreshDelay) ? false : $dashboardWidget->autoRefreshDelay,
'widget_config' => empty($valueConfig['widget_config']) ? array() : $valueConfig['widget_config']
);
$this->set('widget_id', $widget_id);
$this->set('data', $data);

View File

@ -18,12 +18,45 @@ class GalaxiesController extends AppController
public function index()
{
$aclConditions = array();
$filters = $this->IndexFilter->harvestParameters(array('context', 'value'));
$contextConditions = array();
if (empty($filters['context'])) {
$filters['context'] = 'all';
}
$searchConditions = array();
if (empty($filters['value'])) {
$filters['value'] = '';
} else {
$searchall = '%' . strtolower($filters['value']) . '%';
$searchConditions = array(
'OR' => array(
'LOWER(Galaxy.name) LIKE' => $searchall,
'LOWER(Galaxy.namespace) LIKE' => $searchall,
'LOWER(Galaxy.description) LIKE' => $searchall,
'LOWER(Galaxy.kill_chain_order) LIKE' => $searchall,
'Galaxy.uuid LIKE' => $searchall
)
);
}
if ($this->_isRest()) {
$galaxies = $this->Galaxy->find('all', array('recursive' => -1));
$galaxies = $this->Galaxy->find('all',
array(
'recursive' => -1,
'conditions' => array(
'AND' => array($contextConditions, $searchConditions, $aclConditions)
)
)
);
return $this->RestResponse->viewData($galaxies, $this->response->type());
} else {
$this->paginate['conditions']['AND'][] = $contextConditions;
$this->paginate['conditions']['AND'][] = $searchConditions;
$this->paginate['conditions']['AND'][] = $aclConditions;
$galaxies = $this->paginate();
$this->set('list', $galaxies);
$this->set('galaxyList', $galaxies);
$this->set('context', $filters['context']);
$this->set('searchall', $filters['value']);
}
}

View File

@ -33,14 +33,21 @@ class GalaxyClustersController extends AppController
public function index($id)
{
$filters = $this->IndexFilter->harvestParameters(array('context', 'searchall'));
$contextConditions = array();
if (empty($filters['context'])) {
$filters['context'] = 'all';
}
$this->set('context', $filters['context']);
$this->set('searchall', isset($filters['searchall']) ? $filters['searchall'] : '');
$this->paginate['conditions'] = array('GalaxyCluster.galaxy_id' => $id);
if (isset($this->params['named']['searchall']) && strlen($this->params['named']['searchall']) > 0) {
if (isset($filters['searchall']) && strlen($filters['searchall']) > 0) {
$synonym_hits = $this->GalaxyCluster->GalaxyElement->find(
'list',
array(
'recursive' => -1,
'conditions' => array(
'LOWER(GalaxyElement.value) LIKE' => '%' . strtolower($this->params['named']['searchall']) . '%',
'LOWER(GalaxyElement.value) LIKE' => '%' . strtolower($filters['searchall']) . '%',
'GalaxyElement.key' => 'synonyms' ),
'fields' => array(
'GalaxyElement.galaxy_cluster_id')
@ -49,19 +56,21 @@ class GalaxyClustersController extends AppController
$this->paginate['conditions'] =
array("AND" => array(
'OR' => array(
"LOWER(GalaxyCluster.value) LIKE" => '%'. strtolower($this->params['named']['searchall']) .'%',
"LOWER(GalaxyCluster.description) LIKE" => '%'. strtolower($this->params['named']['searchall']) .'%',
"LOWER(GalaxyCluster.value) LIKE" => '%'. strtolower($filters['searchall']) .'%',
"LOWER(GalaxyCluster.description) LIKE" => '%'. strtolower($filters['searchall']) .'%',
"GalaxyCluster.id" => array_values($synonym_hits)
),
"GalaxyCluster.galaxy_id" => $id
));
$this->set('passedArgsArray', array('all'=>$this->params['named']['searchall']));
$this->set('passedArgsArray', array('all'=>$filters['searchall']));
}
$clusters = $this->paginate();
$sgs = $this->GalaxyCluster->Tag->EventTag->Event->SharingGroup->fetchAllAuthorised($this->Auth->user());
foreach ($clusters as $k => $cluster) {
if (!empty($cluster['Tag']['id'])) {
$clusters[$k]['GalaxyCluster']['event_count'] = $this->GalaxyCluster->Tag->EventTag->countForTag($cluster['Tag']['id'], $this->Auth->user(), $sgs);
} else {
$clusters[$k]['GalaxyCluster']['event_count'] = 0;
}
}
$tagIds = array();

View File

@ -25,5 +25,8 @@ $(document).ready(function () {
grid.on('added', function(event, items) {
resetDashboardGrid(grid);
});
grid.on('gsresizestop', function(event, element) {
$(element).find('.widgetContentInner').trigger('widget-resized')
});
});
</script>

View File

@ -2,7 +2,7 @@
$widgetHtml = $this->element('/dashboard/Widgets/' . $config['render']);
$scopedHtml = $this->ScopedCSS->createScopedCSS($widgetHtml);
?>
<div id="widgetContentInner_<?= h($widget_id) ?>">
<div id="widgetContentInner_<?= h($widget_id) ?>" class="widgetContentInner">
<?php
echo $scopedHtml['bundle'];
?>

View File

@ -1,5 +1,4 @@
<?php
echo $this->Html->script('d3');
$seed = rand();
if (!empty($data['formula'])) {
echo sprintf(
@ -8,96 +7,519 @@
);
}
?>
<svg id="svg-<?= $seed ?>" width="960" height="500"></svg>
<div id="chartContainer-<?= $seed ?>" style="flex-grow: 1; position:relative;"></div>
<script>
if (typeof d3 === "undefined") { // load d3.js once. This is necessary as d3.js is using global variables for its event listeners (d3.mouse & d3.event)
$.getScript("/js/d3.js", function() {
init();
})
} else { // d3.js is already loaded
init();
}
var margin = {top: 20, right: 80, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
function init() { // variables and functions have their own scope (no override)
'use strict';
var parseDate = d3.time.format("%Y-%m-%d").parse;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.interpolate("basis")
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.count); });
var svg = d3.select('#svg-<?= $seed ?>')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var data = <?= json_encode($data['data']) ?>;
var insight = "<?= h($data['insight']) ?>";
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; }));
data.forEach(function(d) {
d.date = parseDate(d.date);
});
var data_nodes = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {
date: d.date, count: +d[name]
};
})
/**
*
* Data expected format: Array({
* date: (string) "time_format",
* index: (int),
* line1: (int),
* line2: (int),
* ...
* })
* For abscissa linear scale, replace the date key by index
*/
var data = <?= json_encode($data['data']) ?>;
var default_options = {
time_format: '%Y-%m-%d',
abscissa_linear: false,
show_crossair: true,
show_datapoints: true,
show_legend: true,
style: {
xlabel: "Date",
ylabel: "Count",
hideXAxis: false,
hideYAxis: false,
},
max_datapoints: null,
margin: {top: 10, right: 20, bottom: 35, left: 40},
animation_short_duration: 100,
redraw_timeout: 300, // used after resize
};
});
x.domain(d3.extent(data, function(d) { return d.date; }));
var offsetLeftMargin = 0;
var container_id = "#chartContainer-<?= $seed ?>";
y.domain([
d3.min(data_nodes, function(c) { return d3.min(c.values, function(v) { return v.count; }); }),
d3.max(data_nodes, function(c) { return d3.max(c.values, function(v) { return v.count; }); })
]);
var $container = $(container_id);
var $loadingContainer, tooltip_container;
var resize_timeout;
var timeFormatter;
var svg;
var width, height, svg_width, svg_height;
var xAxis, yAxis, cursorX, cursorY;
var x, y, xGrid, yGrid, value_line
var series, line_guides, points, pointsGroup, labels
var colors = d3.scale.category10();
svg.append("g")
.attr("class", "x axis axis_multi_line_chart")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
var options = <?= json_encode(isset($config['widget_config']) ? $config['widget_config'] : array()) ?>;
var options = $.extend(true, {}, default_options, options);
options = _validateOptions(options);
var data_nodes = [];
var data_nodes_active = [];
var chart_data = [];
var legend_labels = [];
var raw_data;
_init();
_init_canvas();
if (data !== undefined) {
update(data)
}
registerListener();
svg.append("g")
.attr("class", "y axis axis_multi_line_chart")
.call(yAxis)
function __parseTextBoolean(text) {
if (text === "true" || text === "1") {
return true;
} else if (text === "false" || text === "0") {
return false;
} else {
return text;
}
}
var data_node = svg.selectAll(".data-node-<?= $seed ?>")
.data(data_nodes)
.enter().append("g")
.attr("class", "data-node-<?= $seed ?>");
function _validateOptions(options) {
options.abscissa_linear = __parseTextBoolean(options.abscissa_linear);
options.show_crossair = __parseTextBoolean(options.show_crossair);
options.show_datapoints = __parseTextBoolean(options.show_datapoints);
options.show_legend = __parseTextBoolean(options.show_legend);
options.style.hideXAxis = __parseTextBoolean(options.style.hideXAxis);
options.style.hideYAxis = __parseTextBoolean(options.style.hideYAxis);
options.max_datapoints = (options.max_datapoints === null || options.max_datapoints === "null") ? null : parseInt(options.max_datapoints);
return options;
}
data_node.append("path")
.attr("class", "line path_multi_line_chart")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.name); });
function registerListener() {
$container.closest('.widgetContentInner').on('widget-resized', function() {
_init_canvas();
_draw();
})
}
data_node.append("text")
.datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
.attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.count) + ")"; })
.attr("x", 3)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
function _init() {
$loadingContainer = $('<div id="loadingChartContainer" style="background: #ffffff9f"><span class="fa fa-spinner fa-spin" style="font-size: xx-large;"></span></div>').css({
position: 'absolute',
left: '0',
right: '0',
top: '0',
bottom: '0',
display: 'flex',
'align-items': 'center',
'justify-content': 'center'
}).hide();
tooltip_container = d3.select('body').append('div')
.classed('tooltip', true)
.style('opacity', 0)
.style('min-width', '120px')
.style('padding', '3px')
.style('background-color', '#000')
.style('color', 'white')
.style('border-radius', '5px')
.style('display', 'none');
$container.append($loadingContainer);
timeFormatter = d3.time.format(options.time_format).parse;
}
function _init_canvas() {
$container.empty();
svg_width = $container.width();
svg_height = $container.height();
width = svg_width - (options.margin.left+offsetLeftMargin) - options.margin.right;
height = svg_height - options.margin.top - options.margin.bottom;
if (options.abscissa_linear) {
x = d3.scale.linear()
.domain(d3.extent(data, function(d) { return d.index; }))
.range([ 0, width ]);
} else {
x = d3.time.scale()
.domain(d3.extent(data, function(d) { return d.date; }))
.range([ 0, width ]);
}
y = d3.scale.linear()
.domain(d3.extent(data, function(d) { return d.value; }))
.range([ height, 0 ]);
yGrid = d3.svg.axis().scale(x).orient("bottom")
.tickSize(-height)
.tickFormat("");
xGrid = d3.svg.axis().scale(y).orient("left")
.ticks(3)
.tickSize(-width)
.tickFormat("");
value_line = d3.svg.line()
.x(function(d) { return x(options.abscissa_linear ? d.index : d.date); })
.y(function(d) { return y(d.count); });
svg = d3.select(container_id)
.append("svg")
.classed('svg-content-responsive', true)
.attr("width", svg_width)
.attr("height", svg_height)
.append("g")
.attr("transform", "translate(" + (options.margin.left+offsetLeftMargin) + "," + options.margin.top + ")");
if (!options.style.hideXAxis) {
svg.append("g")
.attr('class', 'axis axis-x')
.attr("transform", "translate(0," + height + ")")
svg.append("g")
.attr("class", "axis grid grid-y")
.attr("transform", "translate(0," + height + ")");
svg.append("text")
.classed('axis-label', true)
.attr("text-anchor", "end")
.attr("x", width / 2)
.attr("y", height)
.attr("dy", '30px')
.text(options.style.xlabel);
}
if (!options.style.hideYAxis) {
svg.append("g")
.attr('class', 'axis axis-y')
svg.append("g")
.attr("class", "axis grid grid-x");
svg.append("text")
.classed('axis-label', true)
.attr("text-anchor", "middle")
.attr("transform", "rotate(-90 0 " + height / 2 + ")")
.attr("x", 0)
.attr("dy", '-30px')
.attr("y", height / 2)
.text(options.style.ylabel);
}
svg.append('g')
.classed('line-group', true);
if (options.show_crossair) {
var cursorStrokeConfig = {
dasharray: 5,
opacity: 0.3,
width: 0.5
};
cursorX = svg.append('line')
.attr('class', 'cursor-x')
.attr("stroke-width", cursorStrokeConfig.width)
.attr("stroke-dasharray", cursorStrokeConfig.dasharray)
.style("stroke", "#000")
.style('opacity', 0)
.attr('x1', 0)
.attr('y1', height)
.attr('x2', width)
.attr('y2', height)
cursorY = svg.append('line')
.attr('class', 'cursor-x')
.attr("stroke-width", cursorStrokeConfig.width)
.attr("stroke-dasharray", cursorStrokeConfig.dasharray)
.style("stroke", "#000")
.style('opacity', 0)
.attr('x1', 0)
.attr('y1', 0)
.attr('x2', 0)
.attr('y2', height)
var eventContainer = svg.append('rect')
.attr('fill', 'white')
.attr('class', 'overlay')
.attr('width', width)
.attr('height', height)
.on("mousemove", function() {
var d3Mouse = d3.mouse(this);
cursorX
.attr('y1', d3Mouse[1])
.attr('y2', d3Mouse[1])
cursorY
.attr('x1', d3Mouse[0])
.attr('x2', d3Mouse[0])
})
.on("mouseenter", function(e) {
cursorX.style('opacity', cursorStrokeConfig.opacity)
cursorY.style('opacity', cursorStrokeConfig.opacity)
})
.on("mouseleave", function(e) {
cursorX.style('opacity', 0)
cursorY.style('opacity', 0)
})
}
svg.append('g')
.classed('legend', true);
svg.append('g')
.classed('point-group', true);
window.addEventListener("resize", function() {
if (resize_timeout !== undefined) {
clearTimeout(resize_timeout);
}
resize_timeout = setTimeout(function() { redraw_timeout_handler() }, options.redraw_timeout);
});
}
function redraw_timeout_handler(inst) {
clearTimeout(resize_timeout);
_init_canvas();
_draw();
}
function update(data) {
raw_data = data;
chart_data = data;
_parseDataset();
var labelDomain = d3.keys(data[0]).filter(function(key) { return key !== "date"; }); // fetch all lines keys
var totalValues = [];
var totalMax = 0;
data_nodes = labelDomain.map(function(label) { // generate line data for each lines key
return {
name: label,
values: data.map(function(d, index) {
if (totalValues[index] === undefined) {
totalValues[index] = {
index: d.index,
date: d.date,
count: +d[label],
name: "Total"
}
} else {
totalValues[index].count += d[label];
totalMax = totalMax > totalValues[index].count ? totalMax : totalValues[index].count;
}
return {
index: d.index,
date: d.date,
count: +d[label],
name: label
};
}),
disabled: false
};
});
data_nodes.push({
name: "Total",
values: totalValues,
disabled: true
});
labelDomain.unshift("Total");
legend_labels = labelDomain.map(function(label) {
return {
text: label,
disabled: label === "Total" ? true : false
};
});
colors.domain(labelDomain);
data_nodes_active = data_nodes;
// adapt margin left for big numbers
var tmp = svg.append('text').text(totalMax);
offsetLeftMargin = tmp.node().getComputedTextLength() - 25;
if (offsetLeftMargin > 0) {
_init_canvas()
}
tmp.remove();
_draw();
}
function _parseDataset() {
if (typeof chart_data === 'string') {
chart_data = d3.csv.parse(chart_data, function(d){
var parsed_date = timeFormatter(d.date);
return { timestamp: Math.floor(parsed_date.getTime() / 1000), date: parsed_date, value : parseFloat(d.value) }
});
} else if (Array.isArray(chart_data)){
chart_data.forEach(function(entry, i) {
chart_data[i].date = timeFormatter(entry.date);
})
}
}
function _draw() {
data_nodes_active = data_nodes.filter(function(d) {
return !d.disabled;
})
x.domain(d3.extent(chart_data, function(d) { return options.abscissa_linear ? d.index : d.date; }))
y.domain([
d3.min(data_nodes_active, function(c) { return d3.min(c.values, function(v) { return v.count; }); }),
d3.max(data_nodes_active, function(c) { return d3.max(c.values, function(v) { return v.count; }); })
]);
xAxis = svg.select('.axis-x')
.call(d3.svg.axis().scale(x).orient('bottom'));
yAxis = svg.select('.axis-y')
.call(d3.svg.axis().scale(y).orient("left"));
svg.select('.grid-x')
.call(xGrid);
svg.select('.grid-y')
.call(yGrid);
series = svg.select('.line-group')
.selectAll('.line')
.data(data_nodes_active)
series
.enter()
.append('path')
.attr("class","line")
.attr("fill", "none")
.attr("stroke-width", 2.5);
series
.style("stroke", function(d) { ;return colors(d.name); })
.attr("d", function(d) { return value_line(d.values); });
series.exit().remove();
if (options.show_datapoints) {
pointsGroup = svg.select('.point-group')
.selectAll('.line-point')
.data(data_nodes_active)
var pointsGroupEnter = pointsGroup
.enter()
.append('g')
.attr('class', 'line-point')
points = pointsGroup
.selectAll('.d3-line-circle')
.data(function(d){
return options.max_datapoints === null ? d.values :
d.values.filter(function(v, index) {
var split_threshold = Math.ceil(d.values.length / (options.max_datapoints-1)); // -1 to always have first and last points
return (index % (split_threshold-1) == 0) || (index == d.values.length-1); // -1 to center the split in the middle
})
})
points
.enter()
.append('circle')
.attr('class', 'datapoint d3-line-circle')
.attr('r', 5)
points // Update
.attr('cx', function (d) { return x(options.abscissa_linear ? d.index : d.date); })
.attr('cy', function (d) { return y(d.count); })
.style("fill", function(d) { return colors(d.name); })
.on('mouseover', function(d) {
tooltipDate(true, this, d);
})
.on('mouseout', function() {
tooltipDate(false);
})
pointsGroup.exit().remove();
}
if (options.show_legend) {
labels = svg.select('.legend')
.selectAll('.labels')
.data(legend_labels);
var label = labels.enter()
.append('g')
.attr('class', 'labels')
label.append('circle')
label.append('text')
labels.selectAll('circle')
.style('fill', function(d, i){ return colors(d.text) })
.style('stroke', function(d, i){ return colors(d.text) })
.attr('r', 5);
labels.selectAll('text')
.text(function(d) { return d.text })
.style('font-size', '16px')
.style('text-decoration', function(d) { return d.disabled ? 'line-through' : '' })
.attr('fill', function(d) { return d.disabled ? 'gray' : '' })
.attr('text', 'start')
.attr('dy', '.32em')
.attr('dx', '8');
labels.exit().remove();
var ypos = 5, newxpos = 20, xpos;
label
.attr('transform', function(d, i) {
var length = d3.select(this).select('text').node().getComputedTextLength() + 28;
var xpos = newxpos;
if (width < (options.margin.left+offsetLeftMargin) + options.margin.right + xpos + length) {
newxpos = xpos = 20;
ypos += 20;
}
newxpos += length;
return 'translate(' + xpos + ',' + ypos + ')';
})
.on('click', function(d, i) {
d.disabled = !d.disabled;
var label_text = d.text;
var label_disabled = d.disabled;
data_nodes.filter(function(d) { return d.name === label_text; }).forEach(function(data) {
data.disabled = label_disabled
})
_draw()
});
}
}
function tooltipDate(show, d3Element, datum) {
var tooltip = _toggleTooltip(show, d3Element);
if (show) {
tooltip.html(_generate_tooltip(datum));
var tooltipBR = tooltip.node().getBoundingClientRect();
var tooltipHeight = tooltipBR.height;
var tooltipWidth = tooltipBR.width;
var tooltipcx = parseInt(d3.select(d3Element).attr('cx'));
var dcx = 17;
// Flip tooltip position if necessary
if (width < options.margin.right + tooltipcx - dcx + tooltipWidth) {
var tooltipLeft = parseInt(tooltip.style('left').split('px')[0]);
tooltip.style('left', (tooltipLeft - (dcx + tooltipWidth + 15)) + 'px')
}
var tooltipTop = parseInt(tooltip.style('top').split('px')[0]);
tooltip.style('top', (tooltipTop - tooltipHeight/2) + 'px')
}
}
function _toggleTooltip(show, d3Element) {
if (show) {
tooltip_container
.style('display', 'block')
.style('left', (d3.event.pageX + 17) + 'px')
.style('top', (d3.event.pageY) + 'px')
.transition()
.duration(options.animation_short_duration)
.delay(options.animation_short_duration/2)
.style('opacity', '0.7');
} else {
tooltip_container.transition()
.duration(options.animation_short_duration)
.style('opacity', 0)
.delay(options.animation_short_duration)
.style('display', 'none');
}
return tooltip_container;
}
function _generate_tooltip(datum) {
var formated_date = d3.time.format(options.time_format)(datum.date);
var html = $('<p></p>').text(datum.name).html() + ' (' + formated_date + ', <strong>' + $('<p></p>').text(datum.count).html() + '</strong>) ';
return html;
}
};
</script>
<style widget-scoped>
.svg-content-responsive {
display: inline-block;
position: absolute;
left: 0;
}
.path_multi_line_chart {
stroke-width: 1;
fill: none;
@ -109,11 +531,51 @@ var insight = "<?= h($data['insight']) ?>";
stroke-width: 1;
}
.axis_multi_line_chart path,
.axis_multi_line_chart line {
.path,
.line {
fill: none;
stroke: grey;
stroke-width: 1;
stroke-width: 2;
}
.datapoint {
stroke: #ffffff;
fill: steelblue;
stroke-width: 2px;
}
.labels {
cursor: pointer;
background-color: white;
}
.overlay {
fill: none;
stroke: none;
pointer-events: all;
}
.axis path {
stroke-width: 2px;
stroke: #000;
fill: none;
}
.axis line {
stroke: #000;
}
.axis text {
user-select: none;
}
.axis.grid line {
stroke: lightgrey;
stroke-opacity: 0.7;
shape-rendering: crispEdges;
}
.axis.grid path {
stroke-width: 0;
}
</style>

View File

@ -1,3 +1,4 @@
<div>
<?php
foreach ($data as $element) {
if (!empty($element['type']) && $element['type'] === 'gap') {
@ -26,3 +27,5 @@
);
}
}
?>
</div>

View File

@ -63,6 +63,9 @@
}
resize_timeout = setTimeout(function() { resizeDashboardWorldMap() }, 500); // redraw after 500ms
});
$worldmap.closest('.widgetContentInner').on('widget-resized', function() {
resizeDashboardWorldMap();
})
});
}());
</script>

View File

@ -17,7 +17,7 @@
h($data['model']);
$fieldsString = '';
$simpleFieldWhitelist = array(
'default', 'type', 'options', 'placeholder', 'label', 'empty'
'default', 'type', 'options', 'placeholder', 'label', 'empty', 'rows', 'div'
);
$fieldsArrayForPersistence = array();
$formCreate = $this->Form->create($modelForForm);

View File

@ -45,6 +45,16 @@
}
$url .= '/' . $url_param_data_paths;
}
if (!empty($action['url_named_params_data_paths'])) {
if (is_array($action['url_named_params_data_paths'])) {
$temp = array();
foreach ($action['url_named_params_data_paths'] as $namedParam => $path) {
$temp[] = sprintf('%s:%s', h($namedParam), h(Hash::extract($row, $path)[0]));
}
$url_param_data_paths = implode('/', $temp);
}
$url .= '/' . $url_param_data_paths;
}
if (isset($action['postLink'])) {
echo $this->Form->postLink(
'',
@ -66,10 +76,11 @@
}
echo sprintf(
'<a href="%s" title="%s" aria-label="%s" %s><i class="black %s"></i></a> ',
'<a href="%s" title="%s" aria-label="%s" %s %s><i class="black %s"></i></a> ',
$url,
empty($action['title']) ? '' : h($action['title']),
empty($action['title']) ? '' : h($action['title']),
empty($action['dbclickAction']) ? '' : 'class="dblclickActionElement"',
empty($action['onclick']) ? '' : sprintf('onClick="%s"', $action['onclick']),
$this->FontAwesome->getClass($action['icon'])
);

View File

@ -11,7 +11,15 @@
}
}
}
$data = h($data);
if (is_bool($data)) {
$data = sprintf(
'<i class="black fa fa-%s"></i>',
$data ? 'check' : 'times'
);
$data = '';
} else {
$data = h($data);
}
if (!empty($field['onClick'])) {
$data = sprintf(
'<span onClick="%s">%s</span>',

View File

@ -0,0 +1,5 @@
<?php
echo sprintf(
'<i class="black %s"></i>',
$this->FontAwesome->getClass(Hash::extract($row, $field['data_path'])[0])
);

View File

@ -1,5 +1,23 @@
<?php
/**
* - url: url to reference. Can have `%s` in it to be replaced by `data_path` extracted value.
* - url_params_data_paths: add dynamic URL elements such as an id to the URL. Can be an array with each value added in a separate param. Used if `url` does not have a `%s` marker
*/
$data_elements = Hash::extract($row, $field['data_path']);
$url_param_data_paths = '';
$urlWithData = empty($field['url']) ? '#' : h($field['url']);
if (!empty($field['url_params_data_paths'])) {
if (is_array($field['url_params_data_paths'])) {
$temp = array();
foreach ($field['url_params_data_paths'] as $path) {
$temp[] = h(Hash::extract($row, $path)[0]);
}
$url_param_data_paths = implode('/', $temp);
} else {
$url_param_data_paths = h(Hash::extract($row, $field['url_params_data_paths'])[0]);
}
$urlWithData .= '/' . $url_param_data_paths;
}
$links = array();
foreach ($data_elements as $data) {
if (!empty($data['name'])) {
@ -13,6 +31,8 @@
$field['url'],
$data
);
} elseif (!empty($field['url_params_data_paths'])) {
$url = $urlWithData;
} else {
$url = $data;
}

View File

@ -1,5 +1,11 @@
<?php
$orgs = Hash::extract($row, $field['data_path']);
if (!isset($field['fields']['allow_picture'])) {
$field['fields']['allow_picture'] = true;
}
if (!isset($field['fields']['default_org'])) {
$field['fields']['default_org'] = '';
}
if (!empty($orgs)) {
if (!isset($orgs[0])) {
$orgs = array($orgs);
@ -8,14 +14,24 @@
$i = 0;
foreach ($orgs as $org) {
$i++;
echo sprintf(
'<a href="%s/organisations/view/%s">%s</a>',
$baseurl,
empty($org['id']) ? h($org['uuid']) : h($org['id']),
h($org['name'])
);
if ($i < $count) {
echo '<br />';
if (!empty($org['id'])) {
if ($field['fields']['allow_picture']) {
echo $this->OrgImg->getOrgImg(array('name' => $org['name'], 'id' => $org['id'], 'size' => 24));
} else {
echo sprintf(
'<a href="%s/organisations/view/%s">%s</a>',
$baseurl,
empty($org['id']) ? h($org['uuid']) : h($org['id']),
h($org['name'])
);
}
if ($i < $count) {
echo '<br />';
}
} else {
if ($field['fields']['allow_picture']) {
echo $this->OrgImg->getOrgImg(array('name' => $field['fields']['default_org'], 'size' => 24));
}
}
}
}

View File

@ -0,0 +1,4 @@
<?php
$elementId = Hash::extract($row, $field['data_path'])[0];
echo $this->element('sparkline', array('scope' => $field['csv']['scope'], 'id' => $elementId, 'csv' => $field['csv']['data'][$k]));
?>

View File

@ -29,11 +29,8 @@
}
$skipPagination = isset($data['skip_pagination']) ? $data['skip_pagination'] : 0;
if (!$skipPagination) {
$paginationData = array();
if (!empty($data['paginationBaseurl'])) {
$paginationData['paginationBaseurl'] = $data['paginationBaseurl'];
}
echo $this->element('/genericElements/IndexTable/pagination', $paginationData);
$paginationData = !empty($data['paginatorOptions']) ? $data['paginatorOptions'] : array();
echo $this->element('/genericElements/IndexTable/pagination', array('paginationOptions' => $paginationData));
}
if (!empty($data['top_bar'])) {
echo $this->element('/genericElements/ListTopBar/scaffold', array('data' => $data['top_bar']));
@ -42,10 +39,16 @@
$row_element = isset($data['row_element']) ? $data['row_element'] : 'row';
$options = isset($data['options']) ? $data['options'] : array();
$actions = isset($data['actions']) ? $data['actions'] : array();
$dblclickActionArray = isset($data['actions']) ? Hash::extract($data['actions'], '{n}[dbclickAction]') : array();
$dbclickAction = '';
foreach ($data['data'] as $k => $data_row) {
if (!empty($dblclickActionArray)) {
$dbclickAction = sprintf("changeLocationFromIndexDblclick(%s)", $k);
}
$rows .= sprintf(
'<tr data-row-id="%s">%s</tr>',
'<tr data-row-id="%s" ondblclick="%s">%s</tr>',
h($k),
$dbclickAction,
$this->element(
'/genericElements/IndexTable/' . $row_element,
array(

View File

@ -5,8 +5,8 @@
'before' => '$(".progress").show()',
'complete' => '$(".progress").hide()',
);
if (!empty($paginationBaseurl)) {
$options['url'] = $paginationBaseurl;
if (!empty($paginationOptions)) {
$options = array_merge($options, $paginationOptions);
}
echo $this->Paginator->options($options);
echo sprintf(

View File

@ -1,6 +1,7 @@
<?php
$rowHtml = '';
foreach ($fields as $column => $field) {
$field['data_path'] = empty($field['data_path']) ? '' : $field['data_path'];
if (!isset($field['requirement']) || $field['requirement']) {
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'], 'k' => $k, 'column' => $column));

View File

@ -22,11 +22,12 @@
$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" data-searchkey="%s">',
'<input type="text" class="span3 input-small" placeholder="%s" aria-label="%s" style="padding: 2px 6px;" id="%s" data-searchkey="%s" value="%s">',
empty($data['placeholder']) ? '' : h($data['placeholder']),
empty($data['placeholder']) ? '' : h($data['placeholder']),
empty($data['id']) ? 'quickFilterField' : h($data['id']),
empty($data['searchKey']) ? 'searchall' : h($data['searchKey'])
empty($data['searchKey']) ? 'searchall' : h($data['searchKey']),
empty($data['value']) ? '' : h($data['value'])
);
echo sprintf(
'<div class="btn-group pull-right"><div class="input-append" style="margin-bottom:0px;">%s%s</div></div>',

View File

@ -124,7 +124,7 @@
echo 'Accept: application/json' . PHP_EOL;
echo 'Content-type: application/json';
?></pre>
<code>{"request": {"type":"ip", "eventid":["!51","!62"],"withAttachment":false,"tags":["APT1","!OSINT"],"from":false,"to":"2015-02-15"}}</code><br /><br />
<code>{"request": {"type": "ip", "eventid": ["!51","!62"],"withAttachment": false,"tags": ["APT1","!OSINT"],"from": false,"to": "2015-02-15"}}</code><br /><br />
<p>XML:</p>
<pre><?php
echo 'Headers' . PHP_EOL;

View File

@ -1,84 +1,109 @@
<div class="regexp index">
<h2><?php echo __('Galaxies');?></h2>
<div class="pagination">
<ul>
<?php
$this->Paginator->options(array(
'update' => '.span12',
'evalScripts' => true,
'before' => '$(".progress").show()',
'complete' => '$(".progress").hide()',
));
echo $this->Paginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
echo $this->Paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
?>
</ul>
</div>
<table class="table table-striped table-hover table-condensed">
<tr>
<th><?php echo $this->Paginator->sort('id');?></th>
<th><?php echo $this->Paginator->sort('icon', __('Icon'));?></th>
<th><?php echo $this->Paginator->sort('name');?></th>
<th><?php echo $this->Paginator->sort('version');?></th>
<th><?php echo $this->Paginator->sort('namespace', __('Namespace'));?></th>
<th class="description"><?php echo $this->Paginator->sort('description');?></th>
<th><?php echo __('Actions');?></th>
</tr>
<?php
foreach ($list as $item) {
$row = sprintf(
'<tr><td class="short">%s</td>',
h($item['Galaxy']['id'])
);
$row .= sprintf(
'<td class="short"><span class="%s fa-%s"></span></td>',
$this->FontAwesome->findNamespace($item['Galaxy']['icon']),
h($item['Galaxy']['icon'])
);
$row .= sprintf(
'<td class="short">%s</td>',
h($item['Galaxy']['name'])
);
$row .= sprintf(
'<td class="short">%s</td>',
h($item['Galaxy']['version'])
);
$row .= sprintf(
'<td class="short">%s</td>',
h($item['Galaxy']['namespace'])
);
$row .= sprintf(
'<td>%s</td>',
h($item['Galaxy']['description'])
);
$row .= sprintf(
'<td class="short action-links">%s%s</td></tr>',
$this->Form->postLink('', array('action' => 'delete', $item['Galaxy']['id']), array('class' => 'fa fa-trash', 'title' => __('Delete'), 'aria-label' => __('Delete')), sprintf(__('Are you sure you want to delete the Galaxy (%s)?'), $item['Galaxy']['name'])),
$this->Html->link('', array('action' => 'view', $item['Galaxy']['id']), array('class' => 'fa fa-eye', 'title' => __('View'), 'aria-label' => __('View')))
);
echo $row;
}
?>
</table>
<p>
<?php
echo $this->Paginator->counter(array(
'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')
));
?>
</p>
<div class="pagination">
<ul>
<?php
echo $this->Paginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
echo $this->Paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
?>
</ul>
</div>
</div>
<?php
echo '<div class="index">';
echo $this->element('/genericElements/IndexTable/index_table', array(
'data' => array(
'data' => $galaxyList,
'top_bar' => array(
'children' => array(
array(
'type' => 'simple',
'children' => array(
array(
'active' => $context === 'all',
'url' => $baseurl . '/galaxies/index/context:all',
'text' => __('All'),
),
// array(
// 'active' => $context === 'altered',
// 'url' => $baseurl . '/galaxies/index/context:altered',
// 'text' => __('Altered Galaxies'),
// )
)
),
array(
'type' => 'search',
'button' => __('Filter'),
'placeholder' => __('Enter value to search'),
'data' => '',
'searchKey' => 'value',
'value' => $searchall
)
)
),
'fields' => array(
array(
'name' => __('Galaxy Id'),
'sort' => 'Galaxy.id',
'element' => 'links',
'class' => 'short',
'data_path' => 'Galaxy.id',
'url' => $baseurl . '/galaxies/view/%s'
),
array(
'name' => __('Icon'),
'element' => 'icon',
'class' => 'short',
'data_path' => 'Galaxy.icon',
),
array(
'name' => __('Name'),
'sort' => 'name',
'class' => 'short',
'data_path' => 'Galaxy.name',
),
array(
'name' => __('version'),
'class' => 'short',
'data_path' => 'Galaxy.version',
),
array(
'name' => __('Namespace'),
'class' => 'short',
'data_path' => 'Galaxy.namespace',
),
array(
'name' => __('Description'),
'data_path' => 'Galaxy.description',
)
),
'title' => __('Galaxy index'),
'actions' => array(
array(
'url' => '/galaxies/view',
'url_params_data_paths' => array(
'Galaxy.id'
),
'icon' => 'eye',
'dbclickAction' => true
),
array(
'url' => '/galaxies/delete',
'url_params_data_paths' => array(
'Galaxy.id'
),
'postLink' => true,
'postLinkConfirm' => __('Are you sure you want to delete the Galaxy?'),
'icon' => 'trash'
),
)
)
));
echo '</div>';
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'galaxies', 'menuItem' => 'index'));
?>
<script type="text/javascript">
var passedArgsArray = <?php echo $passedArgs; ?>;
if (passedArgsArray['context'] === undefined) {
passedArgsArray['context'] = 'pending';
}
$(document).ready(function() {
$('#quickFilterButton').click(function() {
runIndexQuickFilter('/context:' + passedArgsArray['context']);
});
$('#quickFilterField').on('keypress', function (e) {
if(e.which === 13) {
runIndexQuickFilter('/context:' + passedArgsArray['context']);
}
});
});
</script>

View File

@ -1,52 +1,50 @@
<?php
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'galaxies', 'menuItem' => 'view'));
$table_data = array();
$table_data[] = array('key' => __('Galaxy ID'), 'value' => $galaxy['Galaxy']['id']);
$table_data[] = array('key' => __('Name'), 'value' => $galaxy['Galaxy']['name']);
$table_data[] = array('key' => __('Namespace'), 'value' => $galaxy['Galaxy']['namespace']);
$table_data[] = array('key' => __('UUID'), 'value' => $galaxy['Galaxy']['uuid']);
$table_data[] = array('key' => __('Description'), 'value' => $galaxy['Galaxy']['description']);
$table_data[] = array('key' => __('Version'), 'value' => $galaxy['Galaxy']['version']);
$kco = '';
if (isset($galaxy['Galaxy']['kill_chain_order'])) {
$kco = '<strong>' . __('Kill chain order') . '</strong> <span class="useCursorPointer fa fa-expand" onclick="$(\'#killChainOrder\').toggle(\'blind\')"></span>';
$kco .= '<div id="killChainOrder" class="hidden" style="border: 1px solid #000; border-radius: 5px; padding: 3px; background: #f4f4f4; margin-left: 20px;">' . json_encode($galaxy['Galaxy']['kill_chain_order']) . '</div>';
}
?>
<div class="galaxy view">
<div class='view'>
<div class="row-fluid">
<div class="span8">
<h2>
<span class="<?php echo $this->FontAwesome->findNamespace($galaxy['Galaxy']['icon']); ?> fa-<?php echo h($galaxy['Galaxy']['icon']); ?>"></span>&nbsp;
<?php echo h($galaxy['Galaxy']['name']); ?> galaxy
</h2>
<dl>
<dt><?php echo __('Galaxy ID');?></dt>
<dd><?php echo h($galaxy['Galaxy']['id']); ?></dd>
<dt><?php echo __('Name');?></dt>
<dd><?php echo $galaxy['Galaxy']['name'] ? h($galaxy['Galaxy']['name']) : h($galaxy['Galaxy']['type']); ?></dd>
<dt><?php echo __('Namespace');?></dt>
<dd><?php echo $galaxy['Galaxy']['namespace'] ? h($galaxy['Galaxy']['namespace']) : 'misp'; ?></dd>
<dt><?php echo __('Uuid');?></dt>
<dd><?php echo h($galaxy['Galaxy']['uuid']); ?></dd>
<dt><?php echo __('Description');?></dt>
<dd><?php echo h($galaxy['Galaxy']['description']); ?></dd>
<dt><?php echo __('Version');?></dt>
<dd><?php echo h($galaxy['Galaxy']['version']); ?></dd>
</dl>
<?php
$kco = '';
if (isset($galaxy['Galaxy']['kill_chain_order'])) {
$kco = '<strong>' . __('Kill chain order') . '</strong> <span class="useCursorPointer fa fa-expand" onclick="$(\'#killChainOrder\').toggle(\'blind\')"></span>';
$kco .= '<div id="killChainOrder" class="hidden" style="border: 1px solid #000; border-radius: 5px; padding: 3px; background: #f4f4f4; margin-left: 20px;">' . json_encode($galaxy['Galaxy']['kill_chain_order']) . '</div>';
}
echo $kco;
?>
<?php echo $this->element('genericElements/viewMetaTable', array('table_data' => $table_data)); ?>
<?php echo $kco; ?>
</div>
</div>
<div id="clusters_div"></div>
</div>
<script type="text/javascript">
$(document).ready(function () {
<?php
$uri = "/galaxy_clusters/index/" . $galaxy['Galaxy']['id'];
if (isset($passedArgsArray)) $uri .= '/searchall:' . $passedArgsArray['all'];
$uri = "/galaxy_clusters/index/" . $galaxy['Galaxy']['id'];
if (isset($passedArgsArray)) {
$uri .= '/searchall:' . $passedArgsArray['all'];
}
?>
$.get("<?php echo h($uri);?>", function(data) {
$("#clusters_div").html(data);
});
var $kco = $('#killChainOrder');
var j = syntaxHighlightJson($kco.text(), 8)
if ($kco && $kco.length > 0) {
var j = syntaxHighlightJson($kco.text(), 8)
}
$kco.html(j);
});
</script>

View File

@ -1,105 +1,103 @@
<div class="pagination">
<ul>
<?php
$this->Paginator->options(array(
<?php
echo $this->element('/genericElements/IndexTable/index_table', array(
'data' => array(
'paginatorOptions' => array(
'update' => '#clusters_div',
'evalScripts' => true,
'before' => '$(".progress").show()',
'complete' => '$(".progress").hide()',
));
echo $this->Paginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
echo $this->Paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
?>
</ul>
</div>
<?php
$tab = "Center";
$filtered = false;
if(isset($passedArgsArray)){
if (count($passedArgsArray) > 0) {
$tab = "Left";
$filtered = true;
}
}
),
'data' => $list,
'top_bar' => array(
'children' => array(
array(
'type' => 'simple',
'children' => array(
array(
'active' => $context === 'all',
'url' => sprintf('%s/galaxies/view/%s/context:all', $baseurl, $galaxy_id),
'text' => __('All'),
),
// array(
// 'active' => $context === 'altered',
// 'url' => sprintf('%s/galaxies/view/%s/context:altered', $baseurl, $galaxy_id),
// 'text' => __('Altered Galaxy Clusters'),
// )
)
),
array(
'type' => 'search',
'button' => __('Filter'),
'placeholder' => __('Enter value to search'),
'data' => '',
'searchKey' => 'value',
'value' => $searchall
)
)
),
'fields' => array(
array(
'name' => __('Value'),
'sort' => 'GalaxyCluster.value',
'element' => 'links',
'class' => 'short',
'data_path' => 'GalaxyCluster.value',
'url_params_data_paths' => 'GalaxyCluster.id',
'url' => $baseurl . '/galaxy_clusters/view'
),
array(
'name' => __('Synonyms'),
'sort' => 'name',
'class' => 'short',
'data_path' => 'GalaxyCluster.synonyms',
),
array(
'name' => __('Activity'),
'class' => 'short',
'data_path' => 'GalaxyCluster.id',
'csv' => array('scope' => 'cluster', 'data' => $csv),
'element' => 'sparkline'
),
array(
'name' => __('#Events'),
'class' => 'short',
'data_path' => 'GalaxyCluster.event_count',
),
array(
'name' => __('Description'),
'sort' => 'description',
'data_path' => 'GalaxyCluster.description',
),
),
'actions' => array(
array(
'title' => 'View graph',
'url' => '/galaxies/viewGraph',
'url_params_data_paths' => array(
'GalaxyCluster.id'
),
'icon' => 'share-alt',
),
array(
'title' => 'View',
'url' => '/galaxy_clusters/view',
'url_params_data_paths' => array(
'GalaxyCluster.id'
),
'icon' => 'eye',
'dbclickAction' => true
),
array(
'title' => 'Delete',
'url' => '/galaxy_clusters/delete',
'url_params_data_paths' => array(
'GalaxyCluster.id'
),
'postLink' => true,
'postLinkConfirm' => __('Are you sure you want to delete the Galaxy Cluster?'),
'icon' => 'trash'
),
)
)
));
?>
<div class="tabMenuFixedContainer" style="display:inline-block;">
<?php if ($filtered):
foreach ($passedArgsArray as $k => $v):?>
<span class="tabMenuFixed tabMenuFixedElement">
<?php echo h(ucfirst($k)) . " : " . h($v); ?>
</span>
<?php endforeach; ?>
<span class="tabMenuFixed tabMenuFixedRight tabMenuSides">
<?php echo $this->Html->link('', array('controller' => 'galaxies', 'action' => 'view/'. $galaxy_id), array('class' => 'icon-remove', 'title' => __('Remove filters')));?>
</span>
<?php endif;?>
<span style="border-right:0px !important;">
<span id="quickFilterButton" role="button" tabindex="0" aria-label="Filter value galaxie cluster" class="tabMenuFilterFieldButton useCursorPointer"
onClick="quickFilter('', '<?php echo $baseurl . '/galaxies/view/' . $galaxy_id; ?>');"><?php echo __('Filter');?></span>
<input class="tabMenuFilterField" type="text" id="quickFilterField">
</span>
</div>
<table class="table table-striped table-hover table-condensed">
<tr>
<th><?php echo $this->Paginator->sort('value');?></th>
<th><?php echo $this->Paginator->sort('synonyms', __('Synonyms'));?></th>
<th><?php echo __('Activity');?></th>
<th><?php echo __('#Events');?></th>
<th><?php echo $this->Paginator->sort('description');?></th>
<th class="actions"><?php echo __('Actions');?></th>
</tr>
<?php
foreach ($list as $k => $item):
?>
<tr>
<td class="short bold"><?php echo h($item['GalaxyCluster']['value']); ?>&nbsp;</td>
<td class="short bold">
<?php
echo nl2br(h(implode("\n", $item['GalaxyCluster']['synonyms'])));
?>
&nbsp;
</td>
<td class="shortish">
<?php echo $this->element('sparkline', array('scope' => 'cluster', 'id' => $item['GalaxyCluster']['id'], 'csv' => $csv[$k])); ?>
</td>
<td class="short">
<?php
if (!empty($item['GalaxyCluster']['event_count'])):
?>
<a href="<?php echo $baseurl; ?>/events/index/searchtag:<?php echo h($item['GalaxyCluster']['tag_id']);?>" class="bold"><?php echo h($item['GalaxyCluster']['event_count']);?></a>
<?php
else:
echo '0';
endif;
?>
</td>
<td><?php echo h($item['GalaxyCluster']['description']); ?>&nbsp;</td>
<td class="short action-links">
<?php echo $this->Html->link('', array('controller' => 'galaxies', 'action' => 'viewGraph', $item['GalaxyCluster']['id']), array('class' => 'fa fa-share-alt', 'title' => __('View graph'), 'aria-label' => __('View graph')));?>
<?php echo $this->Html->link('', array('action' => 'view', $item['GalaxyCluster']['id']), array('class' => 'fa fa-eye', 'title' => __('View'), 'aria-label' => __('View')));?>
<span class="fa fa-trash useCursorPointer" title="<?php echo __('Delete galaxy cluster');?>" role="button" tabindex="0" aria-label="<?php echo __('Delete galaxy cluster');?>" onClick="deleteObject('galaxy_clusters', 'delete', '<?php echo h($item['GalaxyCluster']['id']); ?>', '<?php echo h($item['GalaxyCluster']['id']); ?>');"></span>
</td>
</tr>
<?php
endforeach;
?>
</table>
<p>
<?php
echo $this->Paginator->counter(array('format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')));
?>
</p>
<div class="pagination">
<ul>
<?php
echo $this->Paginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
echo $this->Paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
?>
</ul>
</div>
<script type="text/javascript">
$(document).ready(function(){

View File

@ -1,53 +1,33 @@
<?php
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'galaxies', 'menuItem' => 'view_cluster'));
$table_data = array();
$table_data[] = array('key' => __('Cluster ID'), 'value' => $cluster['GalaxyCluster']['id']);
$table_data[] = array('key' => __('Name'), 'value' => $cluster['GalaxyCluster']['value']);
$table_data[] = array('key' => __('Parent Galaxy'), 'value' => $cluster['Galaxy']['name'] ? $cluster['Galaxy']['name'] : $cluster['Galaxy']['type']);
$table_data[] = array('key' => __('Description'), 'value' => $cluster['GalaxyCluster']['description']);
$table_data[] = array('key' => __('UUID'), 'value' => $cluster['GalaxyCluster']['uuid']);
$table_data[] = array('key' => __('Collection UUID'), 'value' => $cluster['GalaxyCluster']['collection_uuid']);
$table_data[] = array('key' => __('Source'), 'value' => $cluster['GalaxyCluster']['source']);
$table_data[] = array('key' => __('Authors'), 'value' => !empty($cluster['GalaxyCluster']['authors']) ? implode(', ', $cluster['GalaxyCluster']['authors']) : __('N/A'));
$table_data[] = array('key' => __('Connector tag'), 'value' => $cluster['GalaxyCluster']['tag_name']);
$table_data[] = array('key' => __('Events'), 'html' => isset($cluster['GalaxyCluster']['tag_count']) ?
sprintf('<a href="%s">%s %s</a>',
sprintf('%s/events/index/searchtag:%s', $baseurl, h($cluster['GalaxyCluster']['tag_id'])),
h($cluster['GalaxyCluster']['tag_count']),
__('event(s)')
):
'<span>0</span>'
);
?>
<div class="galaxy view">
<div class='view'>
<div class="row-fluid">
<div class="span8">
<h2>
<?php echo isset($cluster['Galax']['name']) ? h($cluster['Galaxy']['name']) : h($cluster['GalaxyCluster']['type']) . ': ' . $cluster['GalaxyCluster']['value']; ?>
<?php echo isset($cluster['Galaxy']['name']) ? h($cluster['Galaxy']['name']) : h($cluster['GalaxyCluster']['type']) . ': ' . $cluster['GalaxyCluster']['value']; ?>
</h2>
<dl>
<dt><?php echo __('Cluster ID');?></dt>
<dd><?php echo h($cluster['GalaxyCluster']['id']); ?></dd>
<dt><?php echo __('Name');?></dt>
<dd><?php echo h($cluster['GalaxyCluster']['value']); ?></dd>
<dt><?php echo __('Parent Galaxy');?></dt>
<dd><?php echo $cluster['Galaxy']['name'] ? h($cluster['Galaxy']['name']) : h($cluster['Galaxy']['type']); ?></dd>
<dt><?php echo __('Description');?></dt>
<dd><?php echo h($cluster['GalaxyCluster']['description']); ?>&nbsp;</dd>
<dt><?php echo __('UUID');?></dt>
<dd><?php echo h($cluster['GalaxyCluster']['uuid']); ?>&nbsp;</dd>
<dt><?php echo __('Collection UUID');?></dt>
<dd><?php echo h($cluster['GalaxyCluster']['collection_uuid']); ?>&nbsp;</dd>
<dt><?php echo __('Source');?></dt>
<dd><?php echo h($cluster['GalaxyCluster']['source']); ?>&nbsp;</dd>
<dt><?php echo __('Authors');?></dt>
<dd>
<?php
$authors = $cluster['GalaxyCluster']['authors'];
if (!empty($authors)) {
echo implode(', ', $authors);
} else {
echo __('N/A');
}
?>
</dd>
<dt><?php echo __('Connector tag');?></dt>
<dd><?php echo h($cluster['GalaxyCluster']['tag_name']); ?></dd>
<dt><?php echo __('Events');?></dt>
<dd>
<?php
if (isset($cluster['GalaxyCluster']['tag_count'])):
?>
<a href="<?php echo $baseurl; ?>/events/index/searchtag:<?php echo h($cluster['GalaxyCluster']['tag_id']); ?>"><?php echo h($cluster['GalaxyCluster']['tag_count']); ?> event(s)</a>
<?php
else:
echo '0';
endif;
?>
</dd>
</dl>
<?php echo $this->element('genericElements/viewMetaTable', array('table_data' => $table_data)); ?>
</div>
</div>
<div class="row-fuild">

View File

@ -37,7 +37,7 @@ App::uses('AppHelper', 'View/Helper');
* - Selector rules must end with either `{` or `,`, their content MUST be put in a new line:
* [bad]
* element { ... }
* [good]
* [good]
* element {
* ...
* }
@ -46,20 +46,20 @@ App::uses('AppHelper', 'View/Helper');
* element,element {
* ...
* }
* [good]
* [good]
* element,
* element {
* ...
* }
* @param string $param1 HTML potentially containing scoped CSS
* @return array Return an array composed of 3 keys (html, css and seed)
* @return array Return an array composed of 3 keys (html, css and seed)
* - bundle: Include both scoped HTML and scoped CSS or the original html if the scoped feature is not requested
* - html: Untouched HTML including nested in a scoped DIV or original html if the scoped feature is not requested
* - css: CSS with an additional filter rule prepended to every selectors or the empty string if the scoped feature is not requested
* - seed: The random generated number
* - originalHtml: Untouched HTML
*/
public function createScopedCSS(string $html) : array
public function createScopedCSS($html)
{
$css = "";
$seed = "";

View File

@ -1795,67 +1795,103 @@
}
},
{
"Feed": {
"id": "114",
"name": "DigitalSide Threat-Intel OSINT Feed",
"provider": "osint.digitalside.it",
"url": "https:\/\/osint.digitalside.it\/Threat-Intel\/digitalside-misp-feed\/",
"rules": "",
"enabled": false,
"distribution": "0",
"sharing_group_id": "0",
"tag_id": "0",
"default": false,
"source_format": "misp",
"fixed_event": true,
"delta_merge": false,
"event_id": "0",
"publish": false,
"override_ids": false,
"settings": "{\"csv\":{\"value\":\"\",\"delimiter\":\",\"},\"common\":{\"excluderegex\":\"\"}}",
"input_source": "network",
"delete_local_file": false,
"lookup_visible": false,
"headers": "",
"caching_enabled": false,
"force_to_ids": false,
"cache_timestamp": "1568901075"
}
},
{
"Feed": {
"id": "115",
"name": "Metasploit exploits with CVE assigned",
"provider": "eCrimeLabs",
"url": "https:\/\/feeds.ecrimelabs.net\/data\/metasploit-cve",
"rules": "{\"tags\":{\"OR\":[],\"NOT\":[]},\"orgs\":{\"OR\":[],\"NOT\":[]}}",
"enabled": true,
"distribution": "0",
"sharing_group_id": "0",
"tag_id": "0",
"default": false,
"source_format": "csv",
"fixed_event": true,
"delta_merge": true,
"event_id": "",
"publish": true,
"override_ids": false,
"settings": "{\"csv\":{\"value\":\"\",\"delimiter\":\",\"},\"common\":{\"excluderegex\":\"\"}}",
"input_source": "network",
"delete_local_file": false,
"lookup_visible": true,
"headers": "",
"caching_enabled": true,
"force_to_ids": false,
"cache_timestamp": "1571206806"
},
"Tag": {
"id": "615",
"name": "osint:source-type=\"block-or-filter-list\"",
"colour": "#004577",
"exportable": true,
"org_id": "0",
"hide_tag": false
}
"Feed": {
"id": "114",
"name": "DigitalSide Threat-Intel OSINT Feed",
"provider": "osint.digitalside.it",
"url": "https://osint.digitalside.it/Threat-Intel/digitalside-misp-feed/",
"rules": "",
"enabled": false,
"distribution": "0",
"sharing_group_id": "0",
"tag_id": "0",
"default": false,
"source_format": "misp",
"fixed_event": true,
"delta_merge": false,
"event_id": "0",
"publish": false,
"override_ids": false,
"settings": "{\"csv\":{\"value\":\"\",\"delimiter\":\",\"},\"common\":{\"excluderegex\":\"\"}}",
"input_source": "network",
"delete_local_file": false,
"lookup_visible": false,
"headers": "",
"caching_enabled": false,
"force_to_ids": false,
"cache_timestamp": "1568901075"
}
},
{
"Feed": {
"id": "115",
"name": "Metasploit exploits with CVE assigned",
"provider": "eCrimeLabs",
"url": "https://feeds.ecrimelabs.net/data/metasploit-cve",
"rules": "{\"tags\":{\"OR\":[],\"NOT\":[]},\"orgs\":{\"OR\":[],\"NOT\":[]}}",
"enabled": true,
"distribution": "0",
"sharing_group_id": "0",
"tag_id": "615",
"default": false,
"source_format": "csv",
"fixed_event": true,
"delta_merge": true,
"event_id": "0",
"publish": true,
"override_ids": false,
"settings": "{\"csv\":{\"value\":\"\",\"delimiter\":\",\"},\"common\":{\"excluderegex\":\"\"}}",
"input_source": "network",
"delete_local_file": false,
"lookup_visible": true,
"headers": "",
"caching_enabled": true,
"force_to_ids": false,
"cache_timestamp": "1571206806"
},
"Tag": {
"id": "615",
"name": "osint:source-type=\"block-or-filter-list\"",
"colour": "#004577",
"exportable": true,
"org_id": "0",
"hide_tag": false
}
},
{
"Feed": {
"id": "116",
"name": "Malware Bazaar",
"provider": "abuse.ch",
"url": "https://bazaar.abuse.ch/export/txt/md5/full/",
"rules": "{\"tags\":{\"OR\":[],\"NOT\":[]},\"orgs\":{\"OR\":[],\"NOT\":[]},\"url_params\":\"\"}",
"enabled": false,
"distribution": "0",
"sharing_group_id": "0",
"tag_id": "615",
"default": false,
"source_format": "csv",
"fixed_event": true,
"delta_merge": false,
"event_id": "0",
"publish": false,
"override_ids": false,
"settings": "{\"csv\":{\"value\":\"\",\"delimiter\":\",\"},\"common\":{\"excluderegex\":\"\\/^#.*\\/i\"}}",
"input_source": "network",
"delete_local_file": false,
"lookup_visible": true,
"headers": "",
"caching_enabled": false,
"force_to_ids": false,
"cache_timestamp": "1571206806"
},
"Tag": {
"id": "615",
"name": "osint:source-type=\"block-or-filter-list\"",
"colour": "#004577",
"exportable": true,
"org_id": "0",
"hide_tag": false
}
}
]

@ -1 +1 @@
Subproject commit d89d185997fd5b9fd47574785141a0ee81383a7e
Subproject commit d577ad8758713e4d7c0523bbe2bead64c941ebdb

View File

@ -2523,3 +2523,14 @@ table tr:hover .down-expand-button {
font-size: 125%;
margin:5px;
}
.grid-stack-item-content {
display: flex;
flex-direction: column;
}
.widgetContent, .widgetContentInner, .widgetContentInner > div {
display: flex;
flex-direction: column;
flex-grow: 1;
}

View File

@ -5023,3 +5023,8 @@ function setHomePage() {
},
});
}
function changeLocationFromIndexDblclick(row_index) {
var href = $('.index table tr[data-row-id=\"' + row_index + '\"] .dblclickActionElement').attr('href')
window.location = href;
}

14
debian/changelog vendored
View File

@ -1,10 +1,16 @@
misp (2.4.221-1) UNRELEASED; urgency=low
misp (2.4.123-1) UNRELEASED; urgency=low
* Bump to release 2.4.221
* Bump to release 2.4.123
-- Sebastien Tricaud <sebastien.tricaud@devo.com> Wed, 12 Feb 2020 14:44:35 -0800
-- Sebastien Tricaud <sebastien.tricaud@devo.com> Thu, 24 Mar 2020 11:10:19 -0800
misp (2.4.220-1) UNRELEASED; urgency=low
misp (2.4.122-1) UNRELEASED; urgency=low
* Bump to release 2.4.122
-- Sebastien Tricaud <sebastien.tricaud@devo.com> Wed, 12 Feb 2020 14:44:35 -0800
misp (2.4.121-1) UNRELEASED; urgency=low
* First package of MISP

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
9

5
debian/control vendored
View File

@ -12,7 +12,10 @@ Package: misp
Architecture: all
Pre-Depends: ${misc:Pre-Depends}
Depends: libapache2-mod-php | php-cgi | php,
ca-certificates,
python3,
python3-setuptools,
python3-wheel,
composer,
mariadb-client,
openssl,
@ -20,6 +23,7 @@ Depends: libapache2-mod-php | php-cgi | php,
unzip,
moreutils,
php-mysql,
php-pear,
php-redis,
php-gd,
php-gnupg,
@ -28,6 +32,7 @@ Depends: libapache2-mod-php | php-cgi | php,
php-readline,
php-mbstring,
php7.3-opcache,
libfuzzy-dev,
${misc:Depends}
Recommends: ${misc:Recommends}, redis-server, mariadb-server
Description: Threat Intelligence Platform

2
debian/install vendored
View File

@ -1,6 +1,8 @@
VERSION.json usr/share/misp
app usr/share/misp
Plugin usr/share/misp
tools usr/share/misp
cti-python-stix2 usr/share/misp
PyMISP usr/share/misp
INSTALL/MYSQL.sql usr/share/doc/misp
INSTALL/misp-workers.service usr/share/doc/misp