diff --git a/app/Controller/TagsController.php b/app/Controller/TagsController.php index 31836287c..3d1760850 100644 --- a/app/Controller/TagsController.php +++ b/app/Controller/TagsController.php @@ -1108,8 +1108,12 @@ class TagsController extends AppController $conditions['OR'][] = array('LOWER(Tag.name) LIKE' => $t); } } else { - foreach ($tag as $k => $t) { - $conditions['OR'][] = array('Tag.name' => $t); + foreach ($tag as $t) { + if (is_numeric($t)) { + $conditions['OR'][] = ['Tag.id' => $t]; + } else { + $conditions['OR'][] = array('Tag.name' => $t); + } } } $tags = $this->Tag->find('all', array( diff --git a/app/Model/GalaxyCluster.php b/app/Model/GalaxyCluster.php index 0c4430a2e..97ffc5fe9 100644 --- a/app/Model/GalaxyCluster.php +++ b/app/Model/GalaxyCluster.php @@ -867,8 +867,18 @@ class GalaxyCluster extends AppModel return $tags; } + /** + * @param string $name + * @param array $user + * @return array|mixed + */ public function getCluster($name, $user) { + $isGalaxyTag = strpos($name, 'misp-galaxy:') === 0; + if (!$isGalaxyTag) { + return null; + } + if (isset($this->__clusterCache[$name])) { return $this->__clusterCache[$name]; } diff --git a/app/View/Elements/ajaxTags.ctp b/app/View/Elements/ajaxTags.ctp index 05711dfa1..0199fb099 100644 --- a/app/View/Elements/ajaxTags.ctp +++ b/app/View/Elements/ajaxTags.ctp @@ -76,7 +76,7 @@ ); if (!empty($tag['Tag']['id'])) { $span_tag = sprintf( - '%s', + '%s', sprintf( '%s%s%s', $baseurl, @@ -86,6 +86,7 @@ $aStyle, $aClass, $aText, + h($tag['Tag']['id']), isset($aTextModified) ? $aTextModified : $aText ); } else { diff --git a/app/View/Elements/galaxyQuickViewMini.ctp b/app/View/Elements/galaxyQuickViewMini.ctp index 3d74f61c3..7df7338e7 100644 --- a/app/View/Elements/galaxyQuickViewMini.ctp +++ b/app/View/Elements/galaxyQuickViewMini.ctp @@ -32,7 +32,7 @@ foreach ($cluster_fields as $cluster_field) { $key = sprintf('%s', Inflector::humanize(h($cluster_field['key']))); if (is_array($cluster_field['value'])) { - if ($cluster_field['key'] == 'refs') { + if ($cluster_field['key'] === 'refs') { $value = array(); foreach ($cluster_field['value'] as $k => $v) { $v_name = $v; @@ -41,25 +41,25 @@ } $value[$k] = '' . h($v_name) . ''; } - $value_contents = nl2br(implode("\n", $value)); - } else if($cluster_field['key'] == 'country') { + $value_contents = implode("
", $value); + } else if ($cluster_field['key'] === 'country') { $value = array(); foreach ($cluster_field['value'] as $k => $v) { $value[] = $this->Icon->countryFlag($v) . ' ' . h($v); } - $value_contents = nl2br(implode("\n", $value)); + $value_contents = implode("
", $value); } else { - $value_contents = nl2br(h(implode("\n", $cluster_field['value']))); + $value_contents = nl2br(h(implode("\n", $cluster_field['value'])), false); } } else { - if ($cluster_field['key'] == 'source' && filter_var($cluster_field['value'], FILTER_VALIDATE_URL)) { - $value_contents = '' . h($cluster_field['value']) . '';; + if ($cluster_field['key'] === 'source' && filter_var($cluster_field['value'], FILTER_VALIDATE_URL)) { + $value_contents = '' . h($cluster_field['value']) . ''; } else { $value_contents = h($cluster_field['value']); } } $value = sprintf('%s', $value_contents); - $popover_data .= sprintf('%s: %s
', $key, $value); + $popover_data .= "$key: $value
"; } echo sprintf( '
%s %s %s %s
', @@ -135,17 +135,3 @@ ); } } -?> - - diff --git a/app/webroot/js/misp.js b/app/webroot/js/misp.js index 5e82f435c..a180d682a 100644 --- a/app/webroot/js/misp.js +++ b/app/webroot/js/misp.js @@ -4894,6 +4894,16 @@ $(document).ready(function() { $this.addClass('fa-eye'); } }); + + // For galaxyQuickViewMini.ctp + $('.expandable[data-clusterid]') + .on('click', function() { + loadClusterRelations($(this).data('clusterid')); + }) + .popover({ + html: true, + trigger: 'hover' + }); }); $(document.body).on("click", ".correlation-expand-button", function() { @@ -5520,3 +5530,102 @@ $('body').on('click', '.hex-value-convert', function() { .attr('aria-label', 'Switch to binary representation'); } }); + +// Tag popover with taxonomy description +(function() { + var tagDataCache = {}; + function fetchTagInfo(tagId, callback) { + if (tagId in tagDataCache) { + callback(tagDataCache[tagId]); + return; + } + + $.ajax({ + success: function (data) { + data = $.parseJSON(data); + var tagData; + for (var i = 0; i < data.length; i++) { + var tag = data[i]; + if (tag.Tag.id == tagId) { + tagData = data[i] + break; + } + } + if (tagData !== undefined) { + callback(tagData); + tagDataCache[tagId] = tagData; + } + }, + type: "get", + url: baseurl + "/tags/search/" + tagId + "/1/1" + }) + } + + function constructTaxonomyInfo(tagData) { + var predicateText = tagData.TaxonomyPredicate.expanded; + if (tagData.TaxonomyPredicate.TaxonomyEntry) { + predicateText += ": " + tagData.TaxonomyPredicate.TaxonomyEntry[0].expanded; + } + + var $predicate = $('
').append( + $('

').css("margin-top", "5px").text('Tag info'), + $('

').css("margin-bottom", "5px").text(predicateText) + ); + if (tagData.TaxonomyPredicate.description) { + $predicate.append($('

').css("margin-bottom", "5px").append( + $('').text('Description: '), + $('').text(tagData.TaxonomyPredicate.description), + )); + } + if (tagData.TaxonomyPredicate.TaxonomyEntry && tagData.TaxonomyPredicate.TaxonomyEntry[0].numerical_value) { + $predicate.append($('

').css("margin-bottom", "5px").append( + $('').text('Numerical value: '), + $('').text(tagData.TaxonomyPredicate.TaxonomyEntry[0].numerical_value), + )); + } + var $meta = $('

').append( + $('

').text('Taxonomy: ' + tagData.Taxonomy.namespace.toUpperCase()), + $('

').css("margin-bottom", "5px").append( + $('').text(tagData.Taxonomy.description), + ) + ) + return $('

').append($predicate, $meta) + } + + var popoverDebounce = null; + $(document.body).on({ + mouseover: function() { + var $tag = $(this); + popoverDebounce = setTimeout(function() { + popoverDebounce = null; + var tagId = $tag.data('tag-id'); + + fetchTagInfo(tagId, function (tagData) { + if (tagData.TaxonomyPredicate === undefined) { + return; + } + // Check if user cursor is still on tag + if ($(':hover').last()[0] !== $tag[0]) { + return; + } + $tag.popover({ + html: true, + container: 'body', + placement: 'top', + template: '
', + content: function () { + return constructTaxonomyInfo(tagData); + } + }).popover('show'); + }); + }, 200); + }, + mouseout: function() { + if (popoverDebounce) { + clearTimeout(popoverDebounce); + popoverDebounce = null; + } + $(this).popover('destroy'); + } + }, 'a.tag[data-tag-id]'); +})();