Merge pull request #8281 from JakubOnderka/freetext-import-simplify

chg: [internal] Simplify and speedup code for freetext importing
pull/8063/merge
Jakub Onderka 2022-04-18 20:11:19 +02:00 committed by GitHub
commit eb86544b72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 2236 additions and 20579 deletions

View File

@ -940,22 +940,14 @@ class AttributesController extends AppController
if (!$changed) {
return new CakeResponse(array('body'=> json_encode(array('errors'=> array('value' => 'nochange'))), 'status'=>200, 'type' => 'json'));
}
$date = new DateTime();
$attribute['Attribute']['timestamp'] = $date->getTimestamp();
$time = time();
$attribute['Attribute']['timestamp'] = $time;
$fieldsToSave = ['timestamp'];
if ($changedKey === 'value') {
$fieldsToSave[] = 'value1';
$fieldsToSave[] = 'value2';
} else {
$fieldsToSave[] = $changedKey;
}
if ($this->Attribute->save($attribute, true, $fieldsToSave)) {
$this->Attribute->Event->unpublishEvent($attribute['Attribute']['event_id'], false, $date->getTimestamp());
if ($this->Attribute->save($attribute)) {
$this->Attribute->Event->unpublishEvent($attribute['Attribute']['event_id'], false, $time);
if ($attribute['Attribute']['object_id'] != 0) {
$this->Attribute->Object->updateTimestamp($attribute['Attribute']['object_id'], $date->getTimestamp());
$this->Attribute->Object->updateTimestamp($attribute['Attribute']['object_id'], $time);
}
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'Field updated.', 'check_publish' => true)), 'status'=>200, 'type' => 'json'));
} else {
@ -1982,12 +1974,6 @@ class AttributesController extends AppController
$result = $this->Attribute->shortDist[$result];
} elseif ($field === 'to_ids') {
$result = ($result == 0 ? 'No' : 'Yes');
} elseif ($field === 'timestamp') {
if (isset($result)) {
$result = date('Y-m-d', $result);
} else {
echo '&nbsp';
}
} elseif ($field === 'value') {
$this->loadModel('Warninglist');
$attribute['Attribute'] = $this->Warninglist->checkForWarning($attribute['Attribute']);

View File

@ -1404,6 +1404,8 @@ class EventsController extends AppController
$advancedFiltering = $this->__checkIfAdvancedFiltering($filters);
$this->set('advancedFilteringActive', $advancedFiltering['active'] ? 1 : 0);
$this->set('advancedFilteringActiveRules', $advancedFiltering['activeRules']);
$this->set('mayModify', $this->__canModifyEvent($event));
$this->set('mayPublish', $this->__canPublishEvent($event));
$this->response->disableCache();
// Remove `focus` attribute from URI
@ -3923,17 +3925,18 @@ class EventsController extends AppController
*/
public function freeTextImport($id, $adhereToWarninglists = false, $returnMetaAttributes = false)
{
$this->request->allowMethod(['post', 'get']);
$event = $this->Event->fetchSimpleEvent($this->Auth->user(), $id);
if (empty($event)) {
throw new MethodNotAllowedException(__('Invalid event.'));
throw new NotFoundException(__('Invalid event.'));
}
$this->set('event_id', $event['Event']['id']);
if ($this->request->is('get')) {
$this->layout = 'ajax';
$this->request->data['Attribute']['event_id'] = $event['Event']['id'];
}
if ($this->request->is('post')) {
} else if ($this->request->is('post')) {
App::uses('ComplexTypeTool', 'Tools');
$complexTypeTool = new ComplexTypeTool();
$this->loadModel('Warninglist');
@ -3947,16 +3950,16 @@ class EventsController extends AppController
if (isset($this->request->data['Attribute']['adhereToWarninglists'])) {
$adhereToWarninglists = $this->request->data['Attribute']['adhereToWarninglists'];
}
$resultArray = $complexTypeTool->checkComplexRouter($this->request->data['Attribute']['value'], 'freetext');
foreach ($resultArray as $key => $r) {
$temp = array();
foreach ($r['types'] as $type) {
$temp[$type] = $type;
}
$resultArray[$key]['types'] = $temp;
}
$resultArray = $complexTypeTool->checkFreeText($this->request->data['Attribute']['value']);
if ($this->_isRest()) {
// Keep this 'types' format for rest response, but it is not necessary for UI
foreach ($resultArray as $key => $r) {
$temp = array();
foreach ($r['types'] as $type) {
$temp[$type] = $type;
}
$resultArray[$key]['types'] = $temp;
}
if ($returnMetaAttributes || !empty($this->request->data['Attribute']['returnMetaAttributes'])) {
return $this->RestResponse->viewData($resultArray, $this->response->type());
} else {
@ -3970,7 +3973,6 @@ class EventsController extends AppController
}
}
$this->Event->Attribute->fetchRelated($this->Auth->user(), $resultArray);
$resultArray = array_values($resultArray);
$typeCategoryMapping = array();
foreach ($this->Event->Attribute->categoryDefinitions as $k => $cat) {
foreach ($cat['types'] as $type) {
@ -3990,15 +3992,10 @@ class EventsController extends AppController
$this->set('mayModify', $this->__canModifyEvent($event));
$this->set('typeDefinitions', $this->Event->Attribute->typeDefinitions);
$this->set('typeCategoryMapping', $typeCategoryMapping);
foreach ($typeCategoryMapping as $k => $v) {
$typeCategoryMapping[$k] = array_values($v);
}
$this->set('mapping', $typeCategoryMapping);
$this->set('resultArray', $resultArray);
$this->set('importComment', '');
$this->set('title_for_layout', __('Freetext Import Results'));
$this->set('title', __('Freetext Import Results'));
$this->loadModel('Warninglist');
$this->set('missingTldLists', $this->Warninglist->missingTldLists());
$this->render('resolved_attributes');
}
@ -4041,19 +4038,17 @@ class EventsController extends AppController
public function saveFreeText($id)
{
if (!$this->request->is('post')) {
throw new MethodNotAllowedException('This endpoint requires a POST request.');
}
$this->request->allowMethod(['post']);
$event = $this->Event->fetchSimpleEvent($this->Auth->user(), $id);
if (!$event) {
throw new NotFoundException(__('Invalid event.'));
}
$this->Event->insertLock($this->Auth->user(), $id);
$attributes = json_decode($this->request->data['Attribute']['JsonObject'], true);
$default_comment = $this->request->data['Attribute']['default_comment'];
$attributes = $this->_jsonDecode($this->request->data['Attribute']['JsonObject']);
$defaultComment = $this->request->data['Attribute']['default_comment'];
$proposals = !$this->__canModifyEvent($event) || (isset($this->request->data['Attribute']['force']) && $this->request->data['Attribute']['force']);
$flashMessage = $this->Event->processFreeTextDataRouter($this->Auth->user(), $attributes, $id, $default_comment, $proposals);
$flashMessage = $this->Event->processFreeTextDataRouter($this->Auth->user(), $attributes, $id, $defaultComment, $proposals);
$this->Flash->info($flashMessage);
if ($this->request->is('ajax')) {

View File

@ -573,21 +573,21 @@ class ObjectsController extends AppController
public function fetchViewValue($id, $field = null)
{
$validFields = array('timestamp', 'comment', 'distribution', 'first_seen', 'last_seen');
if (!isset($field) || !in_array($field, $validFields)) {
if (!isset($field) || !in_array($field, $validFields, true)) {
throw new MethodNotAllowedException('Invalid field requested.');
}
if (!$this->request->is('ajax')) {
throw new MethodNotAllowedException('This function can only be accessed via AJAX.');
}
$params = array(
'conditions' => array('Object.id' => $id),
'fields' => array('id', 'distribution', 'event_id', $field),
'contain' => array(
'Event' => array(
'fields' => array('distribution', 'id', 'org_id'),
)
),
'flatten' => 1
'conditions' => array('Object.id' => $id),
'fields' => array('id', 'distribution', 'event_id', $field),
'contain' => array(
'Event' => array(
'fields' => array('distribution', 'id', 'org_id'),
)
),
'flatten' => 1
);
$object = $this->MispObject->fetchObjectSimple($this->Auth->user(), $params);
if (empty($object)) {
@ -595,10 +595,11 @@ class ObjectsController extends AppController
}
$object = $object[0];
$result = $object['Object'][$field];
if ($field == 'distribution') {
$result=$this->MispObject->shortDist[$result];
if ($field === 'distribution') {
$result = $this->MispObject->shortDist[$result];
}
$this->set('value', $result);
$this->set('field', $field);
$this->layout = 'ajax';
$this->render('ajax/objectViewFieldForm');
}

View File

@ -40,9 +40,6 @@ class ComplexTypeTool
128 => array('single' => array('sha512'), 'composite' => array('filename|sha512'))
);
// algorithms to run through in order, without Hashes that are checked separately
const CHECKS = array('Email', 'IP', 'DomainOrFilename', 'SimpleRegex', 'AS', 'BTC');
private $__tlds = null;
public static function refangValue($value, $type)
@ -179,6 +176,9 @@ class ComplexTypeTool
continue;
}
foreach ($row as $elementPos => $element) {
if (empty($element)) {
continue;
}
if (empty($values) || in_array(($elementPos + 1), $values)) {
$element = trim($element, " \t\n\r\0\x0B\"\'");
if (empty($element)) {
@ -198,23 +198,28 @@ class ComplexTypeTool
return $iocArray;
}
public function checkFreeText($input, $settings = array())
/**
* @param string $input
* @param array $settings
* @return array
*/
public function checkFreeText($input, array $settings = [])
{
$charactersToTrim = '\'".,() ' . "\t\n\r\0\x0B"; // custom + default PHP trim
$input = str_replace("\xc2\xa0", ' ', $input); // non breaking space to normal space
$input = preg_replace('/\p{C}+/u', ' ', $input);
$iocArray = preg_split("/\r\n|\n|\r|\s|\s+|,|\<|\>|;/", $input);
preg_match_all('/\"([^\"]*)\"/', $input, $matches);
foreach ($matches[1] as $match) {
if ($match !== '') {
$iocArray[] = $match;
}
}
preg_match_all('/\"([^\"]*)\"/', $input, $matches);
foreach ($matches[1] as $match) {
if ($match !== '') {
$iocArray[] = $match;
}
}
unset($matches);
$resultArray = [];
foreach ($iocArray as $ioc) {
$ioc = trim($ioc, $charactersToTrim);
$ioc = trim($ioc, '\'".,() ' . "\t\n\r\0\x0B"); // custom + default PHP trim
if (empty($ioc)) {
continue;
}
@ -251,23 +256,37 @@ class ComplexTypeTool
];
}
$input = array('raw' => $raw_input);
$input = ['raw' => $raw_input];
// Check hashes before refang and port extracting, it is not necessary for hashes. This speedups parsing
// freetexts or CSVs with a lot of hashes.
$hashes = $this->__checkForHashes($input);
if ($hashes) {
return $hashes;
if ($result = $this->__checkForHashes($input)) {
return $result;
}
$input = $this->__refangInput($input);
$input = $this->__extractPort($input);
foreach (self::CHECKS as $check) {
$result = $this->{'__checkFor' . $check}($input);
if ($result) {
return $result;
}
// Check email before port extracting, it is not necessary for email. This speedups parsing
// freetexts or CSVs with a lot of emails.
if ($result = $this->__checkForEmail($input)) {
return $result;
}
$input = $this->__extractPort($input);
if ($result = $this->__checkForIP($input)) {
return $result;
}
if ($result = $this->__checkForDomainOrFilename($input)) {
return $result;
}
if ($result = $this->__checkForSimpleRegex($input)) {
return $result;
}
if ($result = $this->__checkForAS($input)) {
return $result;
}
if ($result = $this->__checkForBTC($input)) {
return $result;
}
return false;
}
@ -290,7 +309,12 @@ class ComplexTypeTool
// quick filter for an @ to see if we should validate a potential e-mail address
if (strpos($input['refanged'], '@') !== false) {
if (filter_var($input['refanged'], FILTER_VALIDATE_EMAIL)) {
return array('types' => array('email', 'email-src', 'email-dst', 'target-email', 'whois-registrant-email'), 'to_ids' => true, 'default_type' => 'email-src', 'value' => $input['refanged']);
return [
'types' => array('email', 'email-src', 'email-dst', 'target-email', 'whois-registrant-email'),
'to_ids' => true,
'default_type' => 'email-src',
'value' => $input['refanged'],
];
}
}
return false;
@ -356,17 +380,17 @@ class ComplexTypeTool
private function __refangInput($input)
{
$input['refanged'] = $input['raw'];
$refanged = $input['raw'];
foreach (self::REFANG_REGEX_TABLE as $regex) {
$input['refanged'] = preg_replace($regex['from'], $regex['to'], $input['refanged']);
$refanged = preg_replace($regex['from'], $regex['to'], $refanged);
}
$input['refanged'] = rtrim($input['refanged'], ".");
$refanged = rtrim($refanged, ".");
$input['refanged'] = preg_replace_callback(
'/\[.\]/',
function ($matches) {
return trim($matches[0], '[]');
},
$input['refanged']
$refanged
);
return $input;
}

View File

@ -88,7 +88,7 @@ class TmpFileTool
* @param string $delimiter
* @param string $enclosure
* @param string $escape
* @return Generator
* @return Generator<array>
* @throws Exception
*/
public function intoParsedCsv($delimiter = ',', $enclosure = '"', $escape = "\\")

View File

@ -1023,7 +1023,7 @@ class Attribute extends AppModel
'order' => false,
'limit' => 11,
'flatten' => 1,
'contain' => ['AttributeTag' => false],
'contain' => ['AttributeTag' => false, 'Object' => false],
);
$resultArray[$key]['related'] = $this->fetchAttributes($user, $options);
}

View File

@ -5480,7 +5480,7 @@ class Event extends AppModel
}
$this->Warninglist = ClassRegistry::init('Warninglist');
$complexTypeTool->setTLDs($this->Warninglist->fetchTLDLists());
$freetextResults = array_merge($freetextResults, $complexTypeTool->checkComplexRouter($value, 'FreeText'));
$freetextResults = array_merge($freetextResults, $complexTypeTool->checkFreeText($value));
if (!empty($freetextResults)) {
foreach ($freetextResults as &$ft) {
$temp = array();

View File

@ -1,12 +1,14 @@
<?php
if ($field === 'value') {
echo $this->element('Events/View/value_field', ['object' => $object['Attribute']]);
} elseif ($field === 'timestamp') {
echo $this->Time->date($value);
} else {
if ($value === 'No') {
echo '<input type="checkbox" disabled>';
} else if ($value === 'Yes') {
echo '<input type="checkbox" checked disabled>';
} else {
echo nl2br(h($value)) . '&nbsp;';
echo nl2br(h($value), false);
}
}

View File

@ -335,16 +335,6 @@ echo $this->element('/genericElements/SideMenu/side_menu', ['menuList' => 'event
url = "<?php echo $baseurl; ?>" + "/sightings/advanced/" + object_id + "/" + object_context;
genericPopup(url, '#popover_box');
});
$('.correlation-toggle').click(function() {
var attribute_id = $(this).data('attribute-id');
getPopup(attribute_id, 'attributes', 'toggleCorrelation', '', '#confirmation_box');
return false;
});
$('.toids-toggle').click(function() {
var attribute_id = $(this).data('attribute-id');
getPopup(attribute_id, 'attributes', 'toggleToIDS', '', '#confirmation_box');
return false;
});
popoverStartup();
$(document).on('click', function(e) {
//did not click a popover toggle or popover

View File

@ -3,7 +3,6 @@ $tr_class = '';
if (empty($context)) {
$context = 'event';
}
$linkClass = 'blue';
if ($event['Event']['id'] != $object['event_id']) {
if (!$isSiteAdmin && $event['extensionEvents'][$object['event_id']]['Orgc']['id'] != $me['org_id']) {
$mayModify = false;
@ -34,46 +33,34 @@ if (!empty($k)) {
$objectId = (int) $object['id'];
$quickEdit = function($fieldName) use ($editScope, $object, $event) {
$quickEdit = function($fieldName) use ($mayModify, $object) {
if (!$mayModify) {
return ''; // currently it is not supported to create proposals trough quick edit
}
if ($object['deleted']) {
return ''; // deleted attributes are not editable
}
if ($editScope === 'ShadowAttribute') {
return ''; // currently it is not supported to create proposals trough quick edit
}
if ($fieldName === 'value' && ($object['type'] === 'attachment' || $object['type'] === 'malware-sample')) {
return '';
}
return " onmouseenter=\"quickEditHover(this, '$editScope', '{$object['id']}', '$fieldName', {$event['Event']['id']});\"";
return " data-edit-field=\"$fieldName\"";
}
?>
<tr id="Attribute_<?= $objectId ?>_tr" class="<?php echo $tr_class; ?>" tabindex="0">
<?php
if (($mayModify || !empty($extended)) && empty($disable_multi_select)):
?>
<td style="width:10px;" data-position="<?php echo 'attribute_' . $objectId ?>">
<?php
if ($mayModify):
?>
<input id="select_<?= $objectId ?>" class="select_attribute row_checkbox" type="checkbox" data-id="<?= $objectId ?>" aria-label="<?php echo __('Select attribute');?>" />
<?php
endif;
?>
<tr id="Attribute_<?= $objectId ?>_tr" data-primary-id="<?= $objectId ?>" class="<?php echo $tr_class; ?>" tabindex="0">
<?php if (($mayModify || !empty($extended)) && empty($disable_multi_select)): ?>
<td style="width:10px">
<?php if ($mayModify):?>
<input class="select_attribute" type="checkbox" data-id="<?= $objectId ?>" aria-label="<?php echo __('Select attribute');?>">
<?php endif; ?>
</td>
<?php
endif;
?>
<td class="short context hidden">
<?= $objectId ?>
</td>
<?php endif; ?>
<td class="short context hidden"><?= $objectId ?></td>
<td class="short context hidden uuid quickSelect"><?php echo h($object['uuid']); ?></td>
<td class="short context hidden">
<?php echo $this->element('/Events/View/seen_field', array('object' => $object)); ?>
</td>
<td class="short">
<?php echo date('Y-m-d', $object['timestamp']); ?>
</td>
<td class="short timestamp"><?= $this->Time->date($object['timestamp']) ?></td>
<?php
if (!empty($extended)):
?>
@ -100,31 +87,24 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
endif;
endif;
?>
&nbsp;
</td>
<td class="short"<?= $quickEdit('category') ?>>
<div id="Attribute_<?= $objectId ?>_category_placeholder" class="inline-field-placeholder"></div>
<div id="Attribute_<?= $objectId ?>_category_solid" class="inline-field-solid">
<div class="inline-field-solid">
<?php echo h($object['category']); ?>
</div>
</td>
<td class="short"<?= $quickEdit('type') ?>>
<?php
if (!empty($object['object_relation'])):
?>
<?php if (!empty($object['object_relation'])):?>
<div class="bold"><?php echo h($object['object_relation']); ?>:</div>
<?php
endif;
?>
<div id="Attribute_<?= $objectId ?>_type_placeholder" class="inline-field-placeholder"></div>
<div id="Attribute_<?= $objectId ?>_type_solid" class="inline-field-solid">
<?php endif; ?>
<div class="inline-field-solid">
<?php echo h($object['type']); ?>
</div>
</td>
<td id="Attribute_<?= $objectId ?>_container" class="showspaces limitedWidth shortish"<?= $quickEdit('value') ?>>
<div id="Attribute_<?= $objectId ?>_value_placeholder" class="inline-field-placeholder"></div>
<div id="Attribute_<?= $objectId ?>_value_solid" class="inline-field-solid">
<div class="inline-field-solid">
<?php
$value = $this->element('/Events/View/value_field', array('object' => $object));
if (Configure::read('Plugin.Enrichment_hover_enable') && isset($modules) && isset($modules['hover_type'][$object['type']])) {
$commonDataFields = sprintf('data-object-type="Attribute" data-object-id="%s"', $objectId);
$spanExtra = Configure::read('Plugin.Enrichment_hover_popover_only') ? '' : sprintf(' class="eventViewAttributeHover" %s', $commonDataFields);
@ -132,11 +112,11 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
echo sprintf(
'<span%s>%s</span> %s',
$spanExtra,
$this->element('/Events/View/value_field', array('object' => $object, 'linkClass' => $linkClass)),
$value,
$popupButton
);
} else {
echo $this->element('/Events/View/value_field', array('object' => $object, 'linkClass' => $linkClass));
echo $value;
}
?>
</div>
@ -181,9 +161,8 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
?>
</td>
<td class="showspaces bitwider"<?= $quickEdit('comment') ?>>
<div id="Attribute_<?= $objectId ?>_comment_placeholder" class="inline-field-placeholder"></div>
<div id="Attribute_<?= $objectId ?>_comment_solid" class="inline-field-solid">
<?php echo nl2br(h($object['comment'])); ?>&nbsp;
<div class="inline-field-solid">
<?php echo nl2br(h($object['comment']), false); ?>
</div>
</td>
<td class="short" style="padding-top:3px;">
@ -193,7 +172,6 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
aria-label="<?php echo __('Toggle correlation');?>"
title="<?php echo __('Toggle correlation');?>"
type="checkbox"
data-attribute-id="<?= $objectId ?>"
<?php
echo $object['disable_correlation'] ? '' : ' checked';
echo ($mayChangeCorrelation && empty($event['Event']['disable_correlation'])) ? '' : ' disabled';
@ -304,20 +282,10 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
</ul>
</td>
<td class="short">
<div id="Attribute_<?= $objectId ?>_to_ids_placeholder" class="inline-field-placeholder"></div>
<div id="Attribute_<?= $objectId ?>_to_ids_solid" class="inline-field-solid">
<input type="checkbox" class="toids-toggle" id="toids_toggle_<?= $objectId ?>" data-attribute-id="<?= $objectId ?>" aria-label="<?= __('Toggle IDS flag') ?>" title="<?= __('Toggle IDS flag') ?>"<?= $object['to_ids'] ? ' checked' : ''; ?><?= $mayModify ? '' : ' disabled' ?>>
</div>
<input type="checkbox" class="toids-toggle" id="toids_toggle_<?= $objectId ?>" aria-label="<?= __('Toggle IDS flag') ?>" title="<?= __('Toggle IDS flag') ?>"<?= $object['to_ids'] ? ' checked' : ''; ?><?= $mayModify ? '' : ' disabled' ?>>
</td>
<td class="short"<?= $quickEdit('distribution') ?>>
<?php
$turnRed = '';
if ($object['distribution'] == 0) {
$turnRed = 'style="color:red"';
}
?>
<div id="Attribute_<?= $objectId ?>_distribution_placeholder" class="inline-field-placeholder"></div>
<div id="Attribute_<?= $objectId ?>_distribution_solid" <?php echo $turnRed; ?> class="inline-field-solid">
<div class="inline-field-solid<?= $object['distribution'] == 0 ? ' red' : '' ?>">
<?php
if ($object['distribution'] == 4):
?>
@ -340,7 +308,7 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
}
if (!empty($includeDecayScore)): ?>
<td class="decayingScoreField">
<div id="Attribute_<?= $objectId ?>_score_solid" class="inline-field-solid">
<div class="inline-field-solid">
<?php echo $this->element('DecayingModels/View/attribute_decay_score', array('scope' => 'object', 'object' => $object, 'uselink' => true)); ?>
</div>
</td>
@ -352,8 +320,8 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
if ($object['deleted']):
if ($isSiteAdmin || $mayModify):
?>
<span class="fas fa-redo useCursorPointer" title="<?php echo __('Restore attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Restore attribute');?>" onclick="deleteObject('attributes', 'restore', '<?= $objectId ?>', '<?php echo h($event['Event']['id']); ?>');"></span>
<span class="fa fa-trash useCursorPointer" title="<?php echo __('Permanently delete attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Permanently delete attribute');?>" onclick="deleteObject('attributes', 'delete', '<?= $objectId . '/true'; ?>', '<?php echo h($event['Event']['id']); ?>');"></span>
<span class="fas fa-redo useCursorPointer" title="<?php echo __('Restore attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Restore attribute');?>" onclick="deleteObject('attributes', 'restore', '<?= $objectId ?>')"></span>
<span class="fa fa-trash useCursorPointer" title="<?php echo __('Permanently delete attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Permanently delete attribute');?>" onclick="deleteObject('attributes', 'delete', '<?= $objectId . '/true'; ?>')"></span>
<?php
endif;
else:
@ -369,8 +337,8 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
<?php
endif;
?>
<a href="<?php echo $baseurl;?>/shadow_attributes/edit/<?= $objectId ?>" title="<?php echo __('Propose Edit');?>" aria-label="<?php echo __('Propose Edit');?>" class="fa fa-comment useCursorPointer"></a>
<span class="fa fa-trash useCursorPointer" title="<?php echo __('Propose Deletion');?>" role="button" tabindex="0" aria-label="Propose deletion" onclick="deleteObject('shadow_attributes', 'delete', '<?= $objectId ?>', '<?php echo h($event['Event']['id']); ?>');"></span>
<a href="<?php echo $baseurl;?>/shadow_attributes/edit/<?= $objectId ?>" title="<?php echo __('Propose Edit');?>" aria-label="<?php echo __('Propose Edit');?>" class="fa fa-comment"></a>
<span class="fa fa-trash useCursorPointer" title="<?php echo __('Propose Deletion');?>" role="button" tabindex="0" aria-label="Propose deletion" onclick="deleteObject('shadow_attributes', 'delete', '<?= $objectId ?>')"></span>
<?php
if ($isSiteAdmin):
?>
@ -389,15 +357,15 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
<?php
endif;
?>
<a href="<?php echo $baseurl;?>/attributes/edit/<?= $objectId ?>" title="<?php echo __('Edit');?>" aria-label="<?php echo __('Edit');?>" class="fa fa-edit useCursorPointer"></a>
<a href="<?php echo $baseurl;?>/attributes/edit/<?= $objectId ?>" title="<?php echo __('Edit');?>" aria-label="<?php echo __('Edit');?>" class="fa fa-edit"></a>
<?php
if (empty($event['Event']['publish_timestamp'])):
?>
<span class="fa fa-trash useCursorPointer" title="<?php echo __('Permanently delete attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Permanently delete attribute');?>" onclick="deleteObject('attributes', 'delete', '<?= $objectId . '/true'; ?>', '<?php echo h($event['Event']['id']); ?>');"></span>
<span class="fa fa-trash useCursorPointer" title="<?php echo __('Permanently delete attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Permanently delete attribute');?>" onclick="deleteObject('attributes', 'delete', '<?= $objectId . '/true'; ?>')"></span>
<?php
else:
?>
<span class="fa fa-trash useCursorPointer" title="<?php echo __('Soft-delete attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Soft-delete attribute');?>" onclick="deleteObject('attributes', 'delete', '<?= $objectId ?>', '<?php echo h($event['Event']['id']); ?>');"></span>
<span class="fa fa-trash useCursorPointer" title="<?php echo __('Soft-delete attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Soft-delete attribute');?>" onclick="deleteObject('attributes', 'delete', '<?= $objectId ?>')"></span>
<?php
endif;
endif;

View File

@ -1,6 +1,4 @@
<?php
$linkClass = 'white';
$currentType = 'Object';
$tr_class = 'tableHighlightBorderTop borderBlue';
if ($event['Event']['id'] != $object['event_id']) {
if (!$isSiteAdmin && $event['extensionEvents'][$object['event_id']]['Orgc']['id'] != $me['org_id']) {
@ -12,8 +10,15 @@
if (!empty($k)) {
$tr_class .= ' row_' . h($k);
}
$quickEdit = function($fieldName) use ($mayModify) {
if (!$mayModify) {
return ''; // without permission it is not possible to edit object
}
return " data-edit-field=\"$fieldName\"";
};
$objectId = intval($object['id']);
?>
<tr id="Object_<?php echo $object['id']; ?>_tr" class="<?php echo $tr_class; ?>" tabindex="0">
<tr id="Object_<?= $objectId ?>_tr" data-primary-id="<?= $objectId ?>" class="<?php echo $tr_class; ?>" tabindex="0">
<?php
if ($mayModify || $extended):
?>
@ -21,16 +26,12 @@
<?php
endif;
?>
<td class="short context hidden">
<?php echo h($object['id']); ?>
</td>
<td class="short context hidden"><?= $objectId ?></td>
<td class="short context hidden uuid quickSelect"><?php echo h($object['uuid']); ?></td>
<td class="short context hidden">
<?php echo $this->element('/Events/View/seen_field', array('object' => $object)); ?>
</td>
<td class="short">
<?php echo date('Y-m-d', $object['timestamp']); ?>
</td>
<td class="short timestamp"><?= $this->Time->date($object['timestamp']) ?></td>
<?php
if ($extended):
?>
@ -51,13 +52,12 @@
endif;
endif;
?>
&nbsp;
</td>
<td colspan="<?= $includeRelatedTags ? 6 : 5 ?>">
<span class="bold"><?php echo __('Object name: ');?></span><?php echo h($object['name']);?>
<span class="fa fa-expand useCursorPointer" title="<?php echo __('Expand or Collapse');?>" role="button" tabindex="0" aria-label="<?php echo __('Expand or Collapse');?>" data-toggle="collapse" data-target="#Object_<?php echo h($object['id']); ?>_collapsible"></span>
<br />
<div id="Object_<?php echo $object['id']; ?>_collapsible" class="collapse">
<span class="fa fa-expand useCursorPointer" title="<?php echo __('Expand or Collapse');?>" role="button" tabindex="0" aria-label="<?php echo __('Expand or Collapse');?>" data-toggle="collapse" data-target="#Object_<?php echo $objectId ?>_collapsible"></span>
<br>
<div id="Object_<?= $objectId ?>_collapsible" class="collapse">
<span class="bold"><?php echo __('UUID');?>: </span><?php echo h($object['uuid']);?><br />
<span class="bold"><?php echo __('Meta-category: ');?></span><?php echo h($object['meta-category']);?><br />
<span class="bold"><?php echo __('Description: ');?></span><?php echo h($object['description']);?><br />
@ -77,21 +77,14 @@
}
?>
</td>
<td class="showspaces bitwider" onmouseenter="quickEditHover(this, 'Object', '<?php echo $object['id']; ?>', 'comment', <?php echo $event['Event']['id'];?>);">
<div id="Object_<?php echo $object['id']; ?>_comment_placeholder" class="inline-field-placeholder"></div>
<div id="Object_<?php echo $object['id']; ?>_comment_solid" class="inline-field-solid">
<?php echo nl2br(h($object['comment'])); ?>&nbsp;
<td class="showspaces bitwider"<?= $quickEdit('comment') ?>>
<div class="inline-field-solid">
<?= nl2br(h($object['comment']), false); ?>
</div>
</td>
<td colspan="4">&nbsp;
</td>
<td class="shortish" onmouseenter="quickEditHover(this, 'Object', '<?php echo $object['id']; ?>', 'distribution', <?php echo $event['Event']['id'];?>);">
<?php
$turnRed = '';
if ($object['distribution'] == 0) $turnRed = 'style="color:red"';
?>
<div id="<?php echo $currentType . '_' . $object['id'] . '_distribution_placeholder'; ?>" class="inline-field-placeholder"></div>
<div id="<?php echo $currentType . '_' . $object['id'] . '_distribution_solid'; ?>" <?php echo $turnRed; ?> class="inline-field-solid">
<td colspan="4"></td>
<td class="shortish"<?= $quickEdit('distribution') ?>>
<div class="inline-field-solid<?= $object['distribution'] == 0 ? ' red' : '' ?>">
<?php
if ($object['distribution'] == 4):
?>
@ -100,11 +93,10 @@
else:
echo h($shortDist[$object['distribution']]);
endif;
?>&nbsp;
?>
</div>
</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td colspan="2"></td>
<?php
$paddedFields = array('includeSightingdb', 'includeDecayScore');
foreach ($paddedFields as $paddedField) {
@ -118,29 +110,27 @@
if ($mayModify) {
if (empty($object['deleted'])) {
echo sprintf(
'<a href="%s/objects/edit/%s" title="%s" aria-label="%s" class="fa fa-edit white useCursorPointer"></a> ',
'<a href="%s/objects/edit/%s" title="%s" aria-label="%s" class="fa fa-edit white"></a> ',
$baseurl,
h($object['id']),
$objectId,
__('Edit'),
__('Edit')
);
echo sprintf(
'<span class="fa fa-trash white useCursorPointer" title="%1$s" role="button" tabindex="0" aria-label="%1$s" onClick="%2$s"></span>',
'<span class="fa fa-trash white useCursorPointer" title="%1$s" role="button" tabindex="0" aria-label="%1$s" onclick="%2$s"></span>',
(empty($event['Event']['publish_timestamp']) ? __('Permanently delete object') : __('Soft delete object')),
sprintf(
'deleteObject(\'objects\', \'delete\', \'%s\', \'%s\');',
empty($event['Event']['publish_timestamp']) ? h($object['id']) . '/true' : h($object['id']),
h($event['Event']['id'])
'deleteObject(\'objects\', \'delete\', \'%s\');',
empty($event['Event']['publish_timestamp']) ? $objectId . '/true' : $objectId
)
);
} else {
echo sprintf(
'<span class="fa fa-trash white useCursorPointer" title="%1$s" role="button" tabindex="0" aria-label="%1$s" onClick="%2$s"></span>',
'<span class="fa fa-trash white useCursorPointer" title="%1$s" role="button" tabindex="0" aria-label="%1$s" onclick="%2$s"></span>',
__('Permanently delete object'),
sprintf(
'deleteObject(\'objects\', \'delete\', \'%s\', \'%s\');',
h($object['id']) . '/true',
h($event['Event']['id'])
'deleteObject(\'objects\', \'delete\', \'%s\');',
$objectId . '/true'
)
);
}
@ -161,5 +151,5 @@
'child' => $attrKey == $lastElement ? 'last' : true
));
}
echo '<tr class="objectAddFieldTr"><td><span class="fa fa-plus-circle objectAddField" title="' . __('Add an Object Attribute') .'" data-popover-popup="' . $baseurl . '/objects/quickFetchTemplateWithValidObjectAttributes/' . h($object['id']) .'"></span></td></tr>';
echo '<tr class="objectAddFieldTr"><td><span class="fa fa-plus-circle objectAddField" title="' . __('Add an Object Attribute') .'" data-popover-popup="' . $baseurl . '/objects/quickFetchTemplateWithValidObjectAttributes/' . $objectId .'"></span></td></tr>';
}

View File

@ -36,8 +36,8 @@
?>
<tr id="proposal_<?= $object['id'] ?>_tr" class="<?php echo $tr_class; ?>">
<?php if ($mayModify): ?>
<td style="width:10px;" data-position="<?php echo h($object['objectType']) . '_' . h($object['id']); ?>">
<input id = "select_proposal_<?php echo $object['id']; ?>" class="select_proposal row_checkbox" type="checkbox" aria-label="<?php __('Select proposal');?>" data-id="<?php echo $object['id'];?>" />
<td style="width:10px">
<input class="select_proposal" type="checkbox" aria-label="<?php __('Select proposal');?>" data-id="<?php echo $object['id'];?>">
</td>
<?php endif; ?>
<td class="short context hidden">
@ -50,12 +50,10 @@
<?php echo $this->element('/Events/View/seen_field', array('object' => $object)); ?>
</td>
<td class="short">
<div id="<?php echo $currentType . '_' . $object['id'] . '_timestamp_solid'; ?>">
<?php
if (isset($object['timestamp'])) echo date('Y-m-d', $object['timestamp']);
if (isset($object['timestamp'])) echo $this->Time->date($object['timestamp']);
else echo '&nbsp';
?>
</div>
</td>
<?php
if ($extended):
@ -74,32 +72,18 @@
?>
</td>
<td class="short">
<div id="<?php echo $currentType . '_' . $object['id'] . '_category_placeholder'; ?>" class="inline-field-placeholder"></div>
<div id="<?php echo $currentType . '_' . $object['id'] . '_category_solid'; ?>" class="inline-field-solid">
<?php echo h($object['category']); ?>
</div>
</td>
<td class="short">
<div id="<?php echo $currentType . '_' . $object['id'] . '_type_placeholder'; ?>" class="inline-field-placeholder"></div>
<div id="<?php echo $currentType . '_' . $object['id'] . '_type_solid'; ?>" class="inline-field-solid">
<?php echo h($object['type']); ?>
</div>
</td>
<td id="<?php echo h($currentType) . '_' . h($object['id']) . '_container'; ?>" class="showspaces limitedWidth shortish">
<div id="<?php echo $currentType . '_' . $object['id'] . '_value_placeholder'; ?>" class="inline-field-placeholder"></div>
<div id="<?php echo $currentType; ?>_<?php echo $object['id']; ?>_value_solid" class="inline-field-solid">
<?php
echo $this->element('/Events/View/value_field', array('object' => $object, 'linkClass' => $linkClass));
?>
</div>
<?= $this->element('/Events/View/value_field', array('object' => $object, 'linkClass' => $linkClass)); ?>
</td>
<td class="shortish">&nbsp;</td>
<td class="shortish">&nbsp;</td>
<td class="showspaces bitwider">
<div id="<?php echo $currentType . '_' . $object['id'] . '_comment_placeholder'; ?>" class="inline-field-placeholder"></div>
<div id="<?php echo $currentType . '_' . $object['id'] . '_comment_solid'; ?>" class="inline-field-solid">
<?php echo nl2br(h($object['comment'])); ?>&nbsp;
</div>
<?php echo nl2br(h($object['comment']), false); ?>
</td>
<td class="short" style="padding-top:3px;">&nbsp;</td>
<td class="shortish">
@ -145,13 +129,7 @@
</ul>
</td>
<td class="short">
<div id="<?php echo $currentType . '_' . $object['id'] . '_to_ids_placeholder'; ?>" class="inline-field-placeholder"></div>
<div id="<?php echo $currentType . '_' . $object['id'] . '_to_ids_solid'; ?>" class="inline-field-solid">
<?php
if ($object['to_ids']) echo 'Yes';
else echo 'No';
?>
</div>
<?= $object['to_ids'] ? __('Yes') : __('No') ?>
</td>
<td class="shortish">&nbsp;</td>
<td class="shortish">&nbsp;</td>
@ -170,12 +148,12 @@
echo $this->Form->create('Shadow_Attribute', array('id' => 'ShadowAttribute_' . $object['id'] . '_accept', 'url' => $baseurl . '/shadow_attributes/accept/' . $object['id'], 'style' => 'display:none;'));
echo $this->Form->end();
?>
<span class="fas fa-check white useCursorPointer" title="<?php echo __('Accept Proposal');?>" role="button" tabindex="0" aria-label="<?php echo __('Accept proposal');?>" onClick="acceptObject('shadow_attributes', '<?php echo $object['id']; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
<span class="fas fa-check white useCursorPointer" title="<?php echo __('Accept Proposal');?>" role="button" tabindex="0" aria-label="<?php echo __('Accept proposal');?>" onclick="acceptObject('shadow_attributes', '<?php echo $object['id']; ?>');"></span>
<?php
}
if (($event['Orgc']['id'] == $me['org_id'] && $mayModify) || $isSiteAdmin || ($object['org_id'] == $me['org_id'])) {
?>
<span class="fa fa-trash white useCursorPointer" title="<?php echo __('Discard proposal');?>" role="button" tabindex="0" aria-label="<?php echo __('Discard proposal');?>" onClick="deleteObject('shadow_attributes', 'discard' ,'<?php echo $object['id']; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
<span class="fa fa-trash white useCursorPointer" title="<?php echo __('Discard proposal');?>" role="button" tabindex="0" aria-label="<?php echo __('Discard proposal');?>" onclick="deleteObject('shadow_attributes', 'discard' ,'<?php echo $object['id']; ?>');"></span>
<?php
}
?>

View File

@ -34,8 +34,8 @@
<?php
if ($mayModify):
?>
<td style="width:10px;" data-position="<?php echo h($object['objectType']) . '_' . h($object['id']); ?>">
<input id="select_proposal_<?php echo $object['id']; ?>" class="select_proposal row_checkbox" type="checkbox" data-id="<?php echo $object['id'];?>" />
<td style="width:10px;">
<input class="select_proposal" type="checkbox" data-id="<?php echo $object['id'];?>">
</td>
<?php
endif;
@ -73,12 +73,12 @@
echo $this->Form->create('Shadow_Attribute', array('id' => 'ShadowAttribute_' . $object['id'] . '_accept', 'url' => $baseurl . '/shadow_attributes/accept/' . $object['id'], 'style' => 'display:none;'));
echo $this->Form->end();
?>
<span class="fas fa-check white useCursorPointer" title="<?php echo __('Accept Proposal');?>" role="button" tabindex="0" aria-label="<?php echo __('Accept proposal');?>" onClick="acceptObject('shadow_attributes', '<?php echo $object['id']; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
<span class="fas fa-check white useCursorPointer" title="<?php echo __('Accept Proposal');?>" role="button" tabindex="0" aria-label="<?php echo __('Accept proposal');?>" onclick="acceptObject('shadow_attributes', '<?php echo $object['id']; ?>');"></span>
<?php
}
if (($event['Orgc']['id'] == $me['org_id'] && $mayModify) || $isSiteAdmin || ($object['org_id'] == $me['org_id'])) {
?>
<span class="fa fa-trash white useCursorPointer" title="<?php echo __('Discard proposal');?>" role="button" tabindex="0" aria-label="<?php echo __('Discard proposal');?>" onClick="deleteObject('shadow_attributes', 'discard' ,'<?php echo $object['id']; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
<span class="fa fa-trash white useCursorPointer" title="<?php echo __('Discard proposal');?>" role="button" tabindex="0" aria-label="<?php echo __('Discard proposal');?>" onclick="deleteObject('shadow_attributes', 'discard' ,'<?php echo $object['id']; ?>');"></span>
<?php
}
?>

View File

@ -24,23 +24,19 @@ if (isset($sightingsData['data'][$objectId])) {
}
?>
<td class="shortish">
<?php
if ($isAclSighting):
?>
<i class="far fa-thumbs-up useCursorPointer" title="<?php echo __('Add sighting');?>" role="button" tabindex="0" aria-label="<?php echo __('Add sighting');?>" onmouseover="flexibleAddSighting(this, '0', '<?= $objectId ?>', '<?php echo h($object['event_id']);?>', 'top');" onclick="addSighting('0', '<?= $objectId ?>', '<?php echo h($object['event_id']);?>');">&nbsp;</i>
<i class="far fa-thumbs-down useCursorPointer" title="<?php echo __('Mark as false-positive');?>" role="button" tabindex="0" aria-label="<?php echo __('Mark as false-positive');?>" onmouseover="flexibleAddSighting(this, '1', '<?= $objectId ?>', '<?php echo h($object['event_id']);?>', 'bottom');" onclick="addSighting('1', '<?= $objectId ?>', '<?php echo h($object['event_id']);?>');">&nbsp;</i>
<i class="fas fa-wrench useCursorPointer sightings_advanced_add" title="<?php echo __('Advanced sightings');?>" role="button" tabindex="0" aria-label="<?php echo __('Advanced sightings');?>" data-object-id="<?= $objectId ?>" data-object-context="attribute">&nbsp;</i>
<?php
endif;
?>
<span id="sightingCount_<?php echo $objectId; ?>" class="bold" data-placement="top" data-toggle="popover" data-trigger="hover" data-content="<?= h($html) ?>">
<?php if ($isAclSighting): ?>
<i class="far fa-thumbs-up useCursorPointer" title="<?php echo __('Add sighting');?>" role="button" tabindex="0" aria-label="<?php echo __('Add sighting');?>" onmouseover="flexibleAddSighting(this, 0, <?= $objectId ?>, 'top');" onclick="addSighting(0, <?= $objectId ?>)"></i>
<i class="far fa-thumbs-down useCursorPointer" title="<?php echo __('Mark as false-positive');?>" role="button" tabindex="0" aria-label="<?php echo __('Mark as false-positive');?>" onmouseover="flexibleAddSighting(this, 1, <?= $objectId ?>, 'bottom');" onclick="addSighting(1, <?= $objectId ?>)"></i>
<i class="fas fa-wrench useCursorPointer sightings_advanced_add" title="<?php echo __('Advanced sightings');?>" role="button" tabindex="0" aria-label="<?php echo __('Advanced sightings');?>" data-object-id="<?= $objectId ?>" data-object-context="attribute"></i>
<?php endif; ?>
<b id="sightingCount_<?php echo $objectId; ?>" data-placement="top" data-toggle="popover" data-trigger="hover" data-content="<?= h($html) ?>">
(<span class="green"><?= $s ?></span>/<span class="red"><?= $f ?></span>/<span class="orange"><?= $e ?></span>)
</span>
</b>
</td>
<td class="short">
<?php
if (!empty($sightingsData['csv'][$objectId])) {
echo $this->element('sparkline', array('scope' => 'object', 'id' => $objectId, 'csv' => $sightingsData['csv'][$objectId]));
echo $this->element('sparkline_new', array('scope' => 'object', 'id' => $objectId, 'csv' => $sightingsData['csv'][$objectId]));
}
?>
</td>

View File

@ -226,11 +226,10 @@
}).click(function(e) {
if ($(this).is(':checked')) {
if (e.shiftKey) {
selectAllInbetween(lastSelected, this.id);
selectAllInbetween(lastSelected, this);
}
lastSelected = this.id;
lastSelected = this;
}
attributeListAnyAttributeCheckBoxesChecked();
});
$('.distributionNetworkToggle').each(function() {

View File

@ -6,8 +6,6 @@
}
$urlHere = implode('/', $urlHere);
$urlHere = $baseurl . $urlHere;
$mayModify = ($isSiteAdmin || ($isAclModify && $event['Event']['user_id'] == $me['id'] && $event['Orgc']['id'] == $me['org_id']) || ($isAclModifyOrg && $event['Orgc']['id'] == $me['org_id']));
$mayPublish = ($isAclPublish && $event['Orgc']['id'] == $me['org_id']);
$mayChangeCorrelation = !Configure::read('MISP.completely_disable_correlation') && ($isSiteAdmin || ($mayModify && Configure::read('MISP.allow_disabling_correlation')));
$possibleAction = $mayModify ? 'attribute' : 'shadow_attribute';
$all = false;
@ -19,7 +17,7 @@
}
$fieldCount = 11;
$filtered = false;
if(isset($passedArgsArray)){
if (isset($passedArgsArray)){
if (count($passedArgsArray) > 0) {
$filtered = true;
}
@ -69,8 +67,7 @@
'label' => false,
));
echo $this->Form->end();
?>
<?php
echo $this->Form->create('ShadowAttribute', array('id' => 'accept_selected', 'url' => $baseurl . '/shadow_attributes/acceptSelected/' . $event['Event']['id']));
echo $this->Form->input('ids_accept', array(
'type' => 'text',
@ -79,8 +76,7 @@
'label' => false,
));
echo $this->Form->end();
?>
<?php
echo $this->Form->create('ShadowAttribute', array('id' => 'discard_selected', 'url' => $baseurl . '/shadow_attributes/discardSelected/' . $event['Event']['id']));
echo $this->Form->input('ids_discard', array(
'type' => 'text',
@ -111,7 +107,7 @@
if ($extended || ($mayModify && !empty($event['objects']))):
$fieldCount += 1;
?>
<th><input class="select_all" type="checkbox" title="<?php echo __('Select all');?>" role="button" tabindex="0" aria-label="<?php echo __('Select all attributes/proposals on current page');?>" onClick="toggleAllAttributeCheckboxes();" /></th>
<th><input class="select_all" type="checkbox" title="<?php echo __('Select all');?>" role="button" tabindex="0" aria-label="<?php echo __('Select all attributes/proposals on current page');?>" onclick="toggleAllAttributeCheckboxes()"></th>
<?php
endif;
?>
@ -239,18 +235,18 @@ attributes or the appropriate distribution level. If you think there is a mistak
$('.select_attribute').prop('checked', false).click(function(e) {
if ($(this).is(':checked')) {
if (e.shiftKey) {
selectAllInbetween(lastSelected, this.id);
selectAllInbetween(lastSelected, this);
}
lastSelected = this.id;
lastSelected = this;
}
attributeListAnyAttributeCheckBoxesChecked();
});
$('.select_proposal').prop('checked', false).click(function(e){
if ($(this).is(':checked')) {
if (e.shiftKey) {
selectAllInbetween(lastSelected, this.id);
selectAllInbetween(lastSelected, this);
}
lastSelected = this.id;
lastSelected = this;
}
attributeListAnyProposalCheckBoxesChecked();
});
@ -258,16 +254,6 @@ attributes or the appropriate distribution level. If you think there is a mistak
attributeListAnyAttributeCheckBoxesChecked();
attributeListAnyProposalCheckBoxesChecked();
});
$('.correlation-toggle').click(function() {
var attribute_id = $(this).data('attribute-id');
getPopup(attribute_id, 'attributes', 'toggleCorrelation', '', '#confirmation_box');
return false;
});
$('.toids-toggle').click(function() {
var attribute_id = $(this).data('attribute-id');
getPopup(attribute_id, 'attributes', 'toggleToIDS', '', '#confirmation_box');
return false;
});
$('.screenshot').click(function() {
screenshotPopup($(this).attr('src'), $(this).attr('title'));
});
@ -275,15 +261,13 @@ attributes or the appropriate distribution level. If you think there is a mistak
var selected = [];
var object_context = $(this).data('object-context');
var object_id = $(this).data('object-id');
if (object_id == 'selected') {
$(".select_attribute").each(function() {
if ($(this).is(":checked")) {
selected.push($(this).data("id"));
}
if (object_id === 'selected') {
$(".select_attribute:checked").each(function() {
selected.push($(this).data("id"));
});
object_id = selected.join('|');
}
url = "<?php echo $baseurl; ?>" + "/sightings/advanced/" + object_id + "/" + object_context;
var url = "<?php echo $baseurl; ?>" + "/sightings/advanced/" + object_id + "/" + object_context;
genericPopup(url, '#popover_box');
});
});

View File

@ -10,15 +10,13 @@ if ($quickedit) {
$distributionLevel = (Hash::extract($row, $field['data_path'])[0]);
echo sprintf('<div %s>', $quickedit ? sprintf(
" onmouseenter=\"quickEditHover(this, '%s', %s, 'distribution', %s);\"",
" onmouseenter=\"quickEditHover(this, '%s', %s, 'distribution');\"",
$scope,
$objectId,
$event['id']
$objectId
) : '');
if ($quickedit) {
echo sprintf("<div id='%s_%s_distribution_placeholder' class='inline-field-placeholder'></div>", $scope, $objectId);
echo sprintf("<div id='%s_%s_distribution_solid' class='inline-field-solid'>", $scope, $objectId);
echo "<div class='inline-field-solid'>";
}
echo sprintf(

View File

@ -29,12 +29,12 @@ if (isset($sightings['data'][$objectId])) {
if ($isAclSighting) :
?>
<i class="far fa-thumbs-up useCursorPointer" title="<?php echo __('Add sighting'); ?>" role="button" tabindex="0" aria-label="<?php echo __('Add sighting'); ?>" onmouseover="flexibleAddSighting(this, '0', '<?= $objectId ?>', '<?php echo h($object['event_id']); ?>', 'top');" onclick="addSighting('0', '<?= $objectId ?>', '<?php echo h($object['event_id']); ?>');">&nbsp;</i>
<i class="far fa-thumbs-down useCursorPointer" title="<?php echo __('Mark as false-positive'); ?>" role="button" tabindex="0" aria-label="<?php echo __('Mark as false-positive'); ?>" onmouseover="flexibleAddSighting(this, '1', '<?= $objectId ?>', '<?php echo h($object['event_id']); ?>', 'bottom');" onclick="addSighting('1', '<?= $objectId ?>', '<?php echo h($object['event_id']); ?>');">&nbsp;</i>
<i class="fas fa-wrench useCursorPointer sightings_advanced_add" title="<?php echo __('Advanced sightings'); ?>" role="button" tabindex="0" aria-label="<?php echo __('Advanced sightings'); ?>" data-object-id="<?= $objectId ?>" data-object-context="attribute">&nbsp;</i>
<i class="far fa-thumbs-up useCursorPointer" title="<?php echo __('Add sighting'); ?>" role="button" tabindex="0" aria-label="<?php echo __('Add sighting'); ?>" onmouseover="flexibleAddSighting(this, 0, <?= $objectId ?>, 'top');" onclick="addSighting(0, <?= $objectId ?>);"></i>
<i class="far fa-thumbs-down useCursorPointer" title="<?php echo __('Mark as false-positive'); ?>" role="button" tabindex="0" aria-label="<?php echo __('Mark as false-positive'); ?>" onmouseover="flexibleAddSighting(this, 1, <?= $objectId ?>, 'bottom');" onclick="addSighting(1, '<?= $objectId ?>');"></i>
<i class="fas fa-wrench useCursorPointer sightings_advanced_add" title="<?php echo __('Advanced sightings'); ?>" role="button" tabindex="0" aria-label="<?php echo __('Advanced sightings'); ?>" data-object-id="<?= $objectId ?>" data-object-context="attribute"></i>
<?php
endif;
?>
<span id="sightingCount_<?php echo $objectId; ?>" class="bold" data-placement="top" data-toggle="popover" data-trigger="hover" data-content="<?= h($html) ?>">
<b id="sightingCount_<?php echo $objectId; ?>" data-placement="top" data-toggle="popover" data-trigger="hover" data-content="<?= h($html) ?>">
(<span class="green"><?= $s ?></span>/<span class="red"><?= $f ?></span>/<span class="orange"><?= $e ?></span>)
</span>
</b>

View File

@ -0,0 +1,6 @@
<?php if (!empty($csv)): ?>
<div id="spark_<?php echo (isset($scope) ? h($scope) . '_' : ''); ?><?php echo h($id); ?>"></div>
<script>
sparkline('#spark_<?php echo (isset($scope) ? h($scope) . '_' : ''); ?><?php echo h($id); ?>', "<?= $csv ?>");
</script>
<?php endif; ?>

View File

@ -1,7 +1,5 @@
<div class="freetext">
<?php
echo $this->Form->create('Attribute', array('id'));
?>
<?= $this->Form->create('Attribute', array('id')); ?>
<fieldset>
<legend><?php echo __('Freetext Import Tool'); ?></legend>
<div class="add_attribute_fields">
@ -9,35 +7,32 @@ echo $this->Form->create('Attribute', array('id'));
<?php
echo $this->Form->hidden('event_id');
echo $this->Form->input('value', array(
'type' => 'textarea',
'error' => array('escape' => false),
'div' => 'input clear',
'class' => 'input-xxlarge',
'label' => false
'type' => 'textarea',
'error' => array('escape' => false),
'div' => 'input clear',
'class' => 'input-xxlarge',
'label' => false
));
?>
<div class="input clear"></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">
<table>
<tr>
<td style="vertical-align:top">
<button id="submitButton" class="btn btn-primary"><?php echo __('Submit');?></button>
</td>
<td style="width:540px;">
<p style="color:red;font-weight:bold;display:none;text-align:center" id="warning-message"></p>
</td>
<td style="vertical-align:top;">
<span class="btn btn-inverse" id="cancel_attribute_add"><?php echo __('Cancel');?></span>
</td>
</tr>
</table>
</div>
<?php
echo $this->Form->end();
?>
<div class="overlay_spacing">
<table>
<tr>
<td style="vertical-align:top">
<button id="submitButton" class="btn btn-primary"><?php echo __('Submit');?></button>
</td>
<td style="width:540px;">
<p style="color:red;font-weight:bold;display:none;text-align:center" id="warning-message"></p>
</td>
<td style="vertical-align:top;">
<span class="btn btn-inverse" id="cancel_attribute_add"><?php echo __('Cancel');?></span>
</td>
</tr>
</table>
</div>
<?= $this->Form->end(); ?>
</div>
<script type="text/javascript">
@ -48,4 +43,3 @@ $(function() {
$('#AttributeValue').focus();
});
</script>
<?php echo $this->Js->writeBuffer(); // Write cached scripts

View File

@ -9,7 +9,6 @@
echo sprintf('<p class="bold red">%s</p>', $missingTldLists);
}
?>
<p></p>
<?php
$instanceDefault = 5;
if (!empty(Configure::read('MISP.default_attribute_distribution'))) {
@ -22,36 +21,36 @@
echo $this->Form->create('Attribute', array('url' => $baseurl . '/events/saveFreeText/' . $event['Event']['id'], 'class' => 'mainForm'));
if ($isSiteAdmin) {
echo $this->Form->input('force', array(
'checked' => false,
'label' => __('Proposals instead of attributes'),
'checked' => false,
'label' => __('Proposals instead of attributes'),
));
}
echo $this->Form->input('JsonObject', array(
'label' => false,
'type' => 'text',
'style' => 'display:none;',
'value' => '',
'label' => false,
'type' => 'text',
'style' => 'display:none;',
'value' => '',
));
echo $this->Form->input('default_comment', array(
'label' => false,
'type' => 'text',
'style' => 'display:none;',
'value' => $importComment,
'label' => false,
'type' => 'text',
'style' => 'display:none;',
'value' => $importComment,
));
echo $this->Form->end();
?>
<table class="table table-striped table-hover table-condensed">
<tr>
<th><?php echo __('Value');?></th>
<th><?php echo __('Similar Attributes');?></th>
<th><?php echo __('Category');?></th>
<th><?php echo __('Type');?></th>
<th><?php echo __('IDS');?><input type="checkbox" id="checkAllIDS" style="margin-top:0;margin-left:.3em"></th>
<th style="text-align:center;"><?php echo __('Disable Correlation');?><input type="checkbox" id="checkAllDC" style="margin-top:0;margin-left:.3em"></th>
<th><?php echo __('Distribution');?></th>
<th><?php echo __('Comment');?></th>
<th><?php echo __('Tags (separated by comma)');?></th>
<th><?php echo __('Actions');?></th>
<th><?php echo __('Value');?></th>
<th><?php echo __('Similar Attributes');?></th>
<th><?php echo __('Category');?></th>
<th><?php echo __('Type');?></th>
<th><?php echo __('IDS');?><input type="checkbox" id="checkAllIDS" style="margin-top:0;margin-left:.3em"></th>
<th style="text-align:center;"><?php echo __('Disable Correlation');?><input type="checkbox" id="checkAllDC" style="margin-top:0;margin-left:.3em"></th>
<th><?php echo __('Distribution');?></th>
<th><?php echo __('Comment');?></th>
<th><?php echo __('Tags (separated by comma)');?></th>
<th><?php echo __('Actions');?></th>
</tr>
<?php
$options = array();
@ -60,31 +59,31 @@
<tr id="row_<?php echo $k; ?>" class="freetext_row">
<?php
echo $this->Form->input('Attribute' . $k . 'Save', array(
'label' => false,
'style' => 'display:none;',
'value' => 1,
'label' => false,
'style' => 'display:none;',
'value' => 1,
));
echo $this->Form->input('Attribute' . $k . 'Data', array(
'label' => false,
'type' => 'hidden',
'value' => isset($item['data']) ? $item['data'] : false,
'label' => false,
'type' => 'hidden',
'value' => isset($item['data']) ? $item['data'] : false,
));
echo $this->Form->input('Attribute' . $k . 'DataIsHandled', array(
'label' => false,
'type' => 'hidden',
'value' => isset($item['data_is_handled']) ? h($item['data_is_handled']) : false,
'label' => false,
'type' => 'hidden',
'value' => isset($item['data_is_handled']) ? h($item['data_is_handled']) : false,
));
?>
<td>
<?php
echo $this->Form->input('Attribute' . $k . 'Value', array(
'label' => false,
'value' => $item['value'],
'style' => 'padding:0px;height:20px;margin-bottom:0px;width:90%;min-width:400px;',
'div' => false
'label' => false,
'value' => $item['value'],
'style' => 'padding:0px;height:20px;margin-bottom:0px;width:90%;min-width:400px;',
'div' => false
));
?>
<input type="hidden" id="<?php echo 'Attribute' . $k . 'Save'; ?>" value=1 >
<input type="hidden" id="<?php echo 'Attribute' . $k . 'Save'; ?>" value="1">
</td>
<td class="shortish">
<?php
@ -129,8 +128,8 @@
if (isset($item['categories']) && !in_array($category, $item['categories'])) {
continue;
}
echo '<option value="' . $category . '" ';
if ($category == $default) echo 'selected="selected"';
echo '<option';
if ($category == $default) echo ' selected="selected"';
echo '>' . $category . '</option>';
}
?>
@ -140,33 +139,35 @@
<?php
$divVisibility = '';
$selectVisibility = '';
if (count($item['types']) == 1) {
if (count($item['types']) === 1) {
$selectVisibility = 'display:none;';
} else {
$divVisibility = 'style="display:none;"';
if (!in_array(array_keys($item['types']), $options)) $options[] = array_values($item['types']);
if (!in_array($item['types'], $options)) {
$options[] = $item['types'];
}
}
?>
<div id = "<?php echo 'Attribute' . $k . 'TypeStatic'; ?>" <?php echo $divVisibility; ?> ><?php echo h($item['default_type']); ?></div>
<select id = "<?php echo 'Attribute' . $k . 'Type'; ?>" class='typeToggle' style='padding:0px;height:20px;margin-bottom:0px;<?php echo $selectVisibility; ?>'>
<div id="<?php echo 'Attribute' . $k . 'TypeStatic'; ?>" <?php echo $divVisibility; ?> ><?php echo h($item['default_type']); ?></div>
<select id="<?php echo 'Attribute' . $k . 'Type'; ?>" class='typeToggle' style='padding:0px;height:20px;margin-bottom:0px;<?php echo $selectVisibility; ?>'>
<?php
if (!empty($item['types'])) {
foreach ($item['types'] as $type) {
echo '<option value="' . h($type) . '" ';
echo ($type == $item['default_type'] ? 'selected="selected"' : '') . '>' . h($type) . '</option>';
echo '<option';
echo ($type === $item['default_type'] ? ' selected="selected"' : '') . '>' . h($type) . '</option>';
}
}
?>
</select>
</td>
<td class="short" style="width:40px;text-align:center;">
<input type="checkbox" id="<?php echo 'Attribute' . $k . 'To_ids'; ?>" <?php if ($item['to_ids']) echo 'checked'; ?> class="idsCheckbox" />
<input type="checkbox" id="<?php echo 'Attribute' . $k . 'To_ids'; ?>" <?php if ($item['to_ids']) echo 'checked'; ?> class="idsCheckbox">
</td>
<td class="short" style="width:40px;text-align:center;">
<input type="checkbox" id="<?php echo 'Attribute' . $k . 'Disable_correlation'; ?>" <?php if (isset($item['disable_correlation']) && $item['disable_correlation']) echo 'checked'; ?> class="dcCheckbox" />
<input type="checkbox" id="<?php echo 'Attribute' . $k . 'Disable_correlation'; ?>" <?php if (!empty($item['disable_correlation'])) echo 'checked'; ?> class="dcCheckbox">
</td>
<td class="short" style="width:40px;text-align:center;">
<select id = "<?php echo 'Attribute' . $k . 'Distribution'; ?>" class='distributionToggle' style='padding:0px;height:20px;margin-bottom:0px;'>
<select id="<?php echo 'Attribute' . $k . 'Distribution'; ?>" class='distributionToggle' style='padding:0px;height:20px;margin-bottom:0px;'>
<?php
foreach ($distributions as $distKey => $distValue) {
$default = isset($item['distribution']) ? $item['distribution'] : $instanceDefault;
@ -176,7 +177,7 @@
?>
</select>
<div style="display:none;">
<select id = "<?php echo 'Attribute' . $k . 'SharingGroupId'; ?>" class='sgToggle' style='padding:0px;height:20px;margin-top:3px;margin-bottom:0px;'>
<select id="<?php echo 'Attribute' . $k . 'SharingGroupId'; ?>" class='sgToggle' style='padding:0px;height:20px;margin-top:3px;margin-bottom:0px;'>
<?php
foreach ($sgs as $sgKey => $sgValue) {
echo '<option value="' . h($sgKey) . '">' . h($sgValue) . '</option>';
@ -186,13 +187,13 @@
</div>
</td>
<td class="short">
<input type="text" class="freetextCommentField" id="<?php echo 'Attribute' . $k . 'Comment'; ?>" style="padding:0px;height:20px;margin-bottom:0px;" placeholder="<?php echo h($importComment); ?>" <?php if (isset($item['comment']) && $item['comment'] !== false) echo 'value="' . h($item['comment']) . '"'?>/>
<input type="text" class="freetextCommentField" id="<?php echo 'Attribute' . $k . 'Comment'; ?>" style="padding:0px;height:20px;margin-bottom:0px;" placeholder="<?php echo h($importComment); ?>" <?php if (isset($item['comment']) && $item['comment'] !== false) echo 'value="' . h($item['comment']) . '"'?>>
</td>
<td class="short">
<input type="text" class="freetextTagField" id="<?php echo 'Attribute' . $k . 'Tags'; ?>" style="padding:0px;height:20px;margin-bottom:0px;"<?php if (isset($item['tags']) && $item['tags'] !== false) echo 'value="' . h(implode(",",$item['tags'])) . '"'?>/>
<input type="text" class="freetextTagField" id="<?php echo 'Attribute' . $k . 'Tags'; ?>" style="padding:0px;height:20px;margin-bottom:0px;"<?php if (isset($item['tags']) && $item['tags'] !== false) echo 'value="' . h(implode(",",$item['tags'])) . '"'?>>
</td>
<td class="action short">
<span class="fa fa-times useCursorPointer" title="<?php echo __('Remove resolved attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Remove resolved attribute');?>" onClick="freetextRemoveRow('<?php echo $k; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
<span class="fa fa-times useCursorPointer" title="<?php echo __('Remove resolved attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Remove resolved attribute');?>" onclick="freetextRemoveRow('<?php echo $k; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
</td>
</tr>
<?php
@ -209,7 +210,7 @@
?>
</table>
<span>
<button class="btn btn-primary" style="float:left;" onClick="freetextImportResultsSubmit('<?php echo h($event['Event']['id']); ?>', '<?php echo count($resultArray); ?>');"><?php echo __('Submit %s', $scope);?></button>
<button class="btn btn-primary" style="float:left;" onclick="freetextImportResultsSubmit('<?php echo h($event['Event']['id']); ?>', <?= count($resultArray) ?>);"><?php echo __('Submit %s', $scope);?></button>
<span style="float:right">
<?php
if (!empty($optionsRearranged)):
@ -229,7 +230,7 @@
$keys = array_keys($optionsRearranged);
foreach ($optionsRearranged[$keys[0]] as $toElement):
?>
<option value="<?php echo $toElement; ?>"><?php echo $toElement; ?></option>
<option><?php echo $toElement; ?></option>
<?php
endforeach;
?>
@ -244,7 +245,7 @@
<script>
var options = <?php echo json_encode($optionsRearranged);?>;
var typeCategoryMapping = <?php echo json_encode($typeCategoryMapping); ?>;
$(document).ready(function() {
$(function() {
popoverStartup();
$('.typeToggle').on('change', function() {
var currentId = $(this).attr('id');
@ -266,9 +267,10 @@
}
}
*/
$('#' + currentId).empty();
var $categorySelect = $('#' + currentId);
$categorySelect.empty();
for (var category in currentOptions) {
$('#' + currentId).append($("<option></option>").attr("value", category).text(category));
$categorySelect.append(new Option(category, category));
}
});
<?php
@ -276,16 +278,15 @@
?>
$('#changeFrom').change(function(){
changeFreetextImportFrom();
});
$('#changeFrom').trigger('change');
}).trigger('change');
<?php
endif;
?>
$('#checkAllIDS').change(function() {
$('.idsCheckbox').prop('checked', $('#checkAllIDS').is(':checked'));
$('.idsCheckbox').prop('checked', $(this).is(':checked'));
});
$('#checkAllDC').change(function() {
$('.dcCheckbox').prop('checked', $('#checkAllDC').is(':checked'));
$('.dcCheckbox').prop('checked', $(this).is(':checked'));
});
$('.distributionToggle').change(function() {
if ($(this).val() == 4) {
@ -296,6 +297,4 @@
});
});
</script>
<?php
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'event', 'menuItem' => 'freetextResults'));
?>
<?= $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'event', 'menuItem' => 'freetextResults'));

View File

@ -1,16 +1,12 @@
<?php
$mayModify = (($isAclModify && $event['Event']['user_id'] == $me['id'] && $event['Orgc']['id'] == $me['org_id']) || ($isAclModifyOrg && $event['Orgc']['id'] == $me['org_id']));
$mayPublish = ($isAclPublish && $event['Orgc']['id'] == $me['org_id']);
$menuData = array_merge($menuData, ['mayPublish' => $mayPublish, 'mayModify' => $mayModify]);
$scripts = ['doT', 'extendext', 'moment.min', 'query-builder', 'network-distribution-graph'];
echo $this->element('genericElements/assetLoader', array(
echo $this->element('genericElements/assetLoader', [
'css' => ['query-builder.default', 'attack_matrix'],
'js' => ['doT', 'extendext', 'moment.min', 'query-builder', 'network-distribution-graph']
));
'js' => ['doT', 'extendext', 'moment.min', 'query-builder', 'network-distribution-graph', 'd3', 'd3.custom'],
]);
echo $this->element(
'genericElements/SingleViews/single_view',
[
'title' => ($extended ? '[' . __('Extended view') . '] ' : '') . h(nl2br($event['Event']['info'])),
'title' => ($extended ? '[' . __('Extended view') . '] ' : '') . h(nl2br($event['Event']['info'], false)),
'data' => $event,
'fields' => [
[
@ -182,7 +178,7 @@
],
[
'key' => __('#Attributes'),
'raw' => $attribute_count . __n(' (%s Object)', ' (%s Objects)', $object_count, h($object_count))
'raw' => __n('%s (%s Object)', '%s (%s Objects)', $object_count, $attribute_count, h($object_count))
],
[
'key' => __('First recorded change'),
@ -195,7 +191,7 @@
[
'key' => __('Modification map'),
'type' => 'element',
'element' => 'sparkline',
'element' => 'sparkline_new',
'element_params' => [
'scope' => 'modification',
'id' => $event['Event']['id'],
@ -231,7 +227,7 @@
[
'key' => __('Activity'),
'type' => 'element',
'element' => 'sparkline',
'element' => 'sparkline_new',
'element_params' => [
'scope' => 'event',
'id' => $event['Event']['id'],

View File

@ -26,4 +26,17 @@ class TimeHelper extends AppHelper
return '<time>' . h($time) . '</time>';
}
/**
* @param int $date
* @return string
*/
public function date($date)
{
if (empty($date)) {
return '';
}
$date = date('Y-m-d', $date);
return '<time>' . h($date) . '</time>';
}
}

View File

@ -14,7 +14,6 @@
'bootstrap-datepicker',
'bootstrap-colorpicker',
'font-awesome',
'jquery-ui',
'chosen.min',
'main',
'gridstack.min',
@ -26,7 +25,6 @@
$js_collection = array(
'jquery',
'misp-touch',
'jquery-ui',
'chosen.jquery.min',
'gridstack.all'
);
@ -76,6 +74,7 @@
'bootstrap-datepicker',
'bootstrap-colorpicker',
'misp',
'keyboard-shortcuts-definition',
'keyboard-shortcuts'
)
));

View File

@ -12,7 +12,6 @@
'bootstrap-datepicker',
'bootstrap-colorpicker',
'font-awesome',
'jquery-ui',
'chosen.min',
'main',
array('print', array('media' => 'print'))
@ -23,7 +22,6 @@
$js_collection = array(
'jquery',
'misp-touch',
'jquery-ui',
'chosen.jquery.min'
);
echo $this->element('genericElements/assetLoader', array(

View File

@ -1,2 +1,6 @@
<?php
echo nl2br(h($value)) . '&nbsp;';
if ($field === 'timestamp') {
echo $this->Time->date($value);
} else {
echo nl2br(h($value), false);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
function sparkline(elemId, data) {
data = d3.csv.parse(data);
var width = 100;
var height = 25;
var x = d3.scale.linear().range([0, width - 2]);
var y = d3.scale.linear().range([height - 4, 0]);
var parseDate = d3.time.format("%Y-%m-%d").parse;
var line = d3.svg.line()
.interpolate("linear")
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
data.forEach(function(d) {
d.date = parseDate(d.Date);
d.close = +d.Close;
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain(d3.extent(data, function(d) { return d.close; }));
var svg = d3.select(elemId)
.append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', 'translate(0, 2)');
svg.append('path')
.datum(data)
.attr('class', 'sparkline')
.attr('d', line);
svg.append('circle')
.attr('class', 'sparkcircle')
.attr('cx', x(data[data.length - 1].date))
.attr('cy', y(data[data.length - 1].close))
.attr('r', 2);
}

File diff suppressed because it is too large Load Diff

View File

@ -97,7 +97,7 @@ function fetchAddSightingForm(type, attribute_id, onvalue) {
}).fail(xhrFailCallback);
}
function flexibleAddSighting(clicked, type, attribute_id, event_id, placement) {
function flexibleAddSighting(clicked, type, attribute_id, placement) {
var $clicked = $(clicked);
var hoverbroken = false;
$clicked.off('mouseleave.temp').on('mouseleave.temp', function() {
@ -107,7 +107,7 @@ function flexibleAddSighting(clicked, type, attribute_id, event_id, placement) {
$clicked.off('mouseleave.temp');
if ($clicked.is(":hover") && !hoverbroken) {
var html = '<div>'
+ '<button class="btn btn-primary" onclick="addSighting(\'' + type + '\', \'' + attribute_id + '\', \'' + event_id + '\')">This attribute</button>'
+ '<button class="btn btn-primary" onclick="addSighting(\'' + type + '\', \'' + attribute_id + '\')">This attribute</button>'
+ '<button class="btn btn-primary" style="margin-left:5px;" onclick="fetchAddSightingForm(\'' + type + '\', \'' + attribute_id + '\', true)">Global value</button>'
+ '</div>';
openPopover(clicked, html, true, placement);
@ -344,13 +344,13 @@ function submitGenericForm(url, form, target) {
});
}
function acceptObject(type, id, event) {
function acceptObject(type, id) {
var name = '#ShadowAttribute_' + id + '_accept';
var formData = $(name).serialize();
$.ajax({
data: formData,
success: function (data, textStatus) {
updateIndex(event, 'event');
success: function (data) {
updateIndex(null, 'event');
eventUnpublish();
handleGenericAjaxResponse(data);
},
@ -408,18 +408,16 @@ function eventUnpublish() {
$('.notPublished').show();
}
function updateIndex(id, context, newPage) {
if (typeof newPage !== 'undefined') page = newPage;
function updateIndex(id, context) {
var url, div;
if (context == 'event') {
if (context === 'event') {
if (typeof currentUri == 'undefined') {
location.reload();
return true;
}
url = currentUri;
div = "#attributes_div";
}
if (context == 'template') {
} else if (context === 'template') {
url = "/template_elements/index/" + id;
div = "#templateElements";
}
@ -442,7 +440,8 @@ function updateIndex(id, context, newPage) {
});
}
function updateAttributeFieldOnSuccess(name, type, id, field, event) {
function updateFieldOnSuccess($td, type, id, field) {
var objectType = type === 'Object' ? 'objects' : 'attributes';
$.ajax({
beforeSend: function () {
if (field !== 'timestamp') {
@ -451,66 +450,36 @@ function updateAttributeFieldOnSuccess(name, type, id, field, event) {
},
dataType:"html",
cache: false,
success:function (data, textStatus) {
success: function (data) {
if (field !== 'timestamp') {
$(".loading").hide();
$(name + '_solid').html(data);
$(name + '_placeholder').empty();
$(name + '_solid').show();
$td.find('.inline-field-placeholder').remove();
$td.find('.inline-field-solid').html(data).show();
} else {
$('#' + type + '_' + id + '_' + 'timestamp_solid').html(data);
$td.parent().find('td.timestamp').html(data);
}
popoverStartup(); // reactive popovers
},
error: xhrFailCallback,
url: baseurl + "/attributes/fetchViewValue/" + id + "/" + field,
url: baseurl + "/" + objectType +"/fetchViewValue/" + id + "/" + field,
});
}
function updateObjectFieldOnSuccess(name, type, id, field, event) {
$.ajax({
beforeSend: function (XMLHttpRequest) {
if (field != 'timestamp') {
$(".loading").show();
}
},
dataType:"html",
cache: false,
success:function (data, textStatus) {
if (field != 'timestamp') {
$(".loading").hide();
$(name + '_solid').html(data);
$(name + '_placeholder').empty();
$(name + '_solid').show();
} else {
$('#' + type + '_' + id + '_' + 'timestamp_solid').html(data);
}
},
error: xhrFailCallback,
url: baseurl + "/objects/fetchViewValue/" + id + "/" + field,
});
}
function activateField(type, id, field, event) {
resetForms();
function activateField($td, type, id, field) {
resetEditHoverForms();
if (type === 'denyForm') {
return;
}
var objectType, containerName;
if (type === 'Object') {
objectType = 'objects';
containerName = 'Object';
} else {
objectType = 'attributes';
containerName = 'Attribute';
}
var objectType = type === 'Object' ? 'objects' : 'attributes';
var name = '#' + type + '_' + id + '_' + field;
var container_name = '#' + containerName + '_' + id + '_' + field;
xhr({
dataType: "html",
success: function (data) {
$(container_name + '_placeholder').html(data);
postActivationScripts(name, type, id, field, event);
var $placeholder = $('<div class="inline-field-placeholder"></div>').html(data);
$td.find(".inline-field-solid").before($placeholder);
postActivationScripts($td, name, type, id, field);
$td.find(".inline-field-solid").hide();
},
url: "/" + objectType + "/fetchEditForm/" + id + "/" + field,
});
@ -518,40 +487,39 @@ function activateField(type, id, field, event) {
//if someone clicks an inactive field, replace it with the hidden form field. Also, focus it and bind a focusout event, so that it gets saved if the user clicks away.
//If a user presses enter, submit the form
function postActivationScripts(name, type, id, field, event) {
$(name + '_field').focus();
inputFieldButtonActive(name + '_field');
if (field == 'value' || field == 'comment') {
autoresize($(name + '_field')[0]);
$(name + '_field').on('keyup', function () {
function postActivationScripts($td, name, type, id, field) {
var $field = $(name + '_field');
$field.focus();
inputFieldButtonActive($field);
if (field === 'value' || field === 'comment') {
autoresize($field[0]);
$field.on('keyup', function () {
autoresize(this);
});
}
$(name + '_form').submit(function(e){
e.preventDefault();
submitForm(type, id, field, event);
submitForm($td, type, id, field);
return false;
}).bind("focusout", function() {
inputFieldButtonPassive($field);
}).bind("focusin", function(){
inputFieldButtonActive($field);
});
$(name + '_form').bind("focusout", function() {
inputFieldButtonPassive(name + '_field');
var $inlineInputContainer = $field.closest('.inline-input-container');
$inlineInputContainer.children('.inline-input-accept').bind('click', function() {
submitForm($td, type, id, field);
});
$(name + '_form').bind("focusin", function(){
inputFieldButtonActive(name + '_field');
$inlineInputContainer.children('.inline-input-decline').bind('click', function() {
resetEditHoverForms();
});
$(name + '_field').closest('.inline-input-container').children('.inline-input-accept').bind('click', function() {
submitForm(type, id, field, event);
});
$(name + '_field').closest('.inline-input-container').children('.inline-input-decline').bind('click', function() {
resetForms();
});
$(name + '_solid').hide();
}
function quickEditHover(td, type, id, field, event) {
function quickEditHover(td, type, id, field) {
var $td = $(td);
$td.find('#quickEditButton').remove(); // clean all similar if exist
var $div = $('<div id="quickEditButton"></div>');
@ -560,10 +528,10 @@ function quickEditHover(td, type, id, field, event) {
$span.addClass('fa-as-icon fa fa-edit');
$span.css('font-size', '12px');
$div.append($span);
$td.find("[id*=_solid]").append($div);
$td.find(".inline-field-solid").append($div);
$span.click(function() {
activateField(type, id, field, event);
activateField($td, type, id, field);
});
$td.off('mouseleave').on('mouseleave', function() {
@ -571,7 +539,7 @@ function quickEditHover(td, type, id, field, event) {
});
}
function addSighting(type, attribute_id, event_id) {
function addSighting(type, attribute_id) {
var $sightingForm = $('#SightingForm');
$('input[name="data[Sighting][type]"]', $sightingForm).val(type);
$('input[name="data[Sighting][id]"]', $sightingForm).val(attribute_id);
@ -586,21 +554,26 @@ function addSighting(type, attribute_id, event_id) {
$('.sightingsCounter').each(function() {
$(this).html(parseInt($(this).html()) + 1);
});
updateIndex(event_id, 'event');
updateIndex(null, 'event');
}
},
error: function(xhr) {
xhrFailCallback(xhr);
updateIndex(event_id, 'event');
updateIndex(null, 'event');
},
type: "post",
url: baseurl + "/sightings/add/",
});
}
function resetEditHoverForms() {
$('.inline-field-solid').show();
$('.inline-field-placeholder').remove();
}
function resetForms() {
$('.inline-field-solid').show();
$('.inline-field-placeholder').empty();
$('.inline-field-placeholder').hide();
}
function inputFieldButtonActive(selector) {
@ -620,31 +593,52 @@ function autoresize(textarea) {
// submit the form - this can be triggered by unfocusing the activated form field or by submitting the form (hitting enter)
// after the form is submitted, intercept the response and act on it
function submitForm(type, id, field, context) {
function submitForm($td, type, id, field) {
var object_type = 'attributes';
var action = "editField";
var name = '#' + type + '_' + id + '_' + field;
if (type == 'Object') {
if (type === 'Object') {
object_type = 'objects';
}
$.ajax({
data: $(name + '_field').closest("form").serialize(),
cache: false,
success:function (data, textStatus) {
handleAjaxEditResponse(data, name, type, id, field, context);
success: function (data) {
handleAjaxEditResponse($td, data, type, id, field);
},
error:function(xhr) {
error: function(xhr) {
xhrFailCallback(xhr);
updateIndex(context, 'event');
updateIndex(null, 'event');
},
type:"post",
url: baseurl + "/" + object_type + "/" + action + "/" + id
type: "post",
url: baseurl + "/" + object_type + "/editField/" + id
});
$(name + '_field').unbind("keyup");
$(name + '_form').unbind("focusout");
return false;
}
// Event attributes and attributes index and search
(function() {
$(document.body).on('click', '.correlation-toggle', function() {
var attribute_id = $(this).parents('tr').data('primary-id');
getPopup(attribute_id, 'attributes', 'toggleCorrelation', '', '#confirmation_box');
return false;
});
$(document.body).on('click', '.toids-toggle', function() {
var attribute_id = $(this).parents('tr').data('primary-id');
getPopup(attribute_id, 'attributes', 'toggleToIDS', '', '#confirmation_box');
return false;
});
// Show quick edit hover icon for attributes and objects
$(document.body).on('mouseenter', '[data-edit-field]', function() {
var $tr = $(this).parents('tr');
var objectId = $tr.data('primary-id');
var type = $tr.attr('id').startsWith('Object') ? 'Object' : 'Attribute';
var field = $(this).data('edit-field');
quickEditHover(this, type, objectId, field);
});
})();
function quickSubmitTagForm(selected_tag_ids, addData) {
var event_id = addData.id;
var localFlag = '';
@ -765,30 +759,30 @@ function refreshTagCollectionRow(tag_collection_id) {
});
}
function handleAjaxEditResponse(data, name, type, id, field, event) {
responseArray = data;
function handleAjaxEditResponse($td, data, type, id, field) {
var responseArray = data;
if (type === 'Attribute') {
if (responseArray.saved) {
var msg = responseArray.success !== undefined ? responseArray.success : responseArray.message;
showMessage('success', msg);
updateAttributeFieldOnSuccess(name, type, id, field, event);
updateAttributeFieldOnSuccess(name, type, id, 'timestamp', event);
updateFieldOnSuccess($td, type, id, field);
updateFieldOnSuccess($td, type, id, 'timestamp');
eventUnpublish();
} else {
showMessage('fail', 'Validation failed: ' + responseArray.errors.value);
updateAttributeFieldOnSuccess(name, type, id, field, event);
updateFieldOnSuccess($td, type, id, field);
}
} else if (type === 'ShadowAttribute') {
updateIndex(event, 'event');
updateIndex(null, 'event');
} else if (type === 'Object') {
if (responseArray.saved) {
showMessage('success', responseArray.message);
updateObjectFieldOnSuccess(name, type, id, field, event);
updateObjectFieldOnSuccess(name, type, id, 'timestamp', event);
updateFieldOnSuccess($td, type, id, field);
updateFieldOnSuccess($td, type, id, 'timestamp');
eventUnpublish();
} else {
showMessage('fail', 'Validation failed: ' + responseArray.errors.value);
updateObjectFieldOnSuccess(name, type, id, field, event);
updateFieldOnSuccess($td, type, id, field);
}
}
if (responseArray.hasOwnProperty('check_publish')) {
@ -825,11 +819,9 @@ function handleGenericAjaxResponse(data, skip_reload) {
function toggleAllAttributeCheckboxes() {
if ($(".select_all").is(":checked")) {
$(".select_attribute").prop("checked", true);
$(".select_proposal").prop("checked", true);
$(".select_attribute, .select_proposal").prop("checked", true);
} else {
$(".select_attribute").prop("checked", false);
$(".select_proposal").prop("checked", false);
$(".select_attribute, .select_proposal").prop("checked", false);
}
}
@ -953,7 +945,7 @@ function multiSelectDeleteEventBlocklist(on, cache) {
}).fail(xhrFailCallback);
}
function multiSelectAction(event, context) {
function multiSelectAction(event_id, context) {
var settings = {
deleteAttributes: {
confirmation: "Are you sure you want to delete all selected attributes?",
@ -980,25 +972,22 @@ function multiSelectAction(event, context) {
var answer = confirm("Are you sure you want to " + settings[context]["action"] + " all selected " + settings[context]["alias"] + "s?");
if (answer) {
var selected = [];
$(".select_" + settings[context]["alias"]).each(function() {
if ($(this).is(":checked")) {
var temp= $(this).data("id");
selected.push(temp);
}
$(".select_" + settings[context]["alias"] + ":checked").each(function() {
selected.push($(this).data("id"));
});
$('#' + settings[context]["camelCase"] + 'Ids' + settings[context]["action"].ucfirst()).attr('value', JSON.stringify(selected));
var formData = $('#' + settings[context]["action"] + '_selected').serialize();
if (context == 'deleteAttributes') {
var url = $('#delete_selected').attr('action');
} else {
var url = baseurl + "/" + settings[context]["controller"] + "/" + settings[context]["action"] + "Selected/" + event;
var url = baseurl + "/" + settings[context]["controller"] + "/" + settings[context]["action"] + "Selected/" + event_id;
}
xhr({
data: formData,
type:"POST",
url: url,
success: function (data) {
updateIndex(event, 'event');
updateIndex(null, 'event');
var result = handleGenericAjaxResponse(data);
if (settings[context]["action"] != "discard" && result == true) {
eventUnpublish();
@ -1043,11 +1032,9 @@ function unhideSelectedTags(taxonomy) {
function getSelected() {
var selected = [];
$(".select_attribute").each(function() {
if ($(this).is(":checked")) {
var test = $(this).data("id");
selected.push(test);
}
$(".select_attribute:checked").each(function() {
var test = $(this).data("id");
selected.push(test);
});
return JSON.stringify(selected);
}
@ -1102,33 +1089,15 @@ function loadTagCollectionTags(id) {
});
}
function removeEventTag(event, tag) {
var answer = confirm("Are you sure you want to remove this tag from the event?");
if (answer) {
var formData = $('#removeTag_' + tag).serialize();
xhr({
data: formData,
type:"POST",
url: "/events/removeTag/" + event + '/' + tag,
success:function (data) {
loadEventTags(event);
handleGenericAjaxResponse(data);
},
});
}
return false;
}
function loadAttributeTags(id) {
function loadAttributeTags(attribute_id) {
$.ajax({
dataType: "html",
cache: false,
success: function (data) {
// different approach for event view and attribute view
$("#Attribute_" + id + "_tr .attributeTagContainer, [data-primary-id=" + id + "] .attributeTagContainer").html(data);
$("[data-primary-id=" + attribute_id + "] .attributeTagContainer").html(data);
},
error: xhrFailCallback,
url: baseurl + "/tags/showAttributeTag/" + id
url: baseurl + "/tags/showAttributeTag/" + attribute_id
});
}
@ -2675,9 +2644,10 @@ function popoverStartup() {
}
function changeFreetextImportFrom() {
$('#changeTo').find('option').remove();
var $changeTo = $('#changeTo');
$changeTo.empty();
options[$('#changeFrom').val()].forEach(function(element) {
$('#changeTo').append('<option value="' + element + '">' + element + '</option>');
$changeTo.append(new Option(element));
});
}
@ -2689,8 +2659,10 @@ function changeFreetextImportExecute() {
var from = $('#changeFrom').val();
var to = $('#changeTo').val();
$('.typeToggle').each(function() {
if ($( this ).val() == from) {
if (selectContainsOption("#" + $(this).attr('id'), to)) $( this ).val(to);
if ($(this).val() === from) {
if (selectContainsOption("#" + $(this).attr('id'), to)) {
$(this).val(to);
}
}
});
}
@ -2698,7 +2670,7 @@ function changeFreetextImportExecute() {
function selectContainsOption(selectid, value) {
var exists = false;
$(selectid + ' option').each(function(){
if (this.value == value) {
if (this.value === value) {
exists = true;
return false;
}
@ -2729,12 +2701,11 @@ function importChoiceSelect(url, elementId, ajax) {
}
}
function freetextImportResultsSubmit(id, count) {
function freetextImportResultsSubmit(event_id, count) {
var attributeArray = [];
var temp;
for (var i = 0; i < count; i++) {
if ($('#Attribute' + i + 'Save').val() == 1) {
temp = {
attributeArray.push({
value:$('#Attribute' + i + 'Value').val(),
category:$('#Attribute' + i + 'Category').val(),
type:$('#Attribute' + i + 'Type').val(),
@ -2746,18 +2717,17 @@ function freetextImportResultsSubmit(id, count) {
data:$('#Attribute' + i + 'Data').val(),
data_is_handled:$('#Attribute' + i + 'DataIsHandled').val(),
tags:$('#Attribute' + i + 'Tags').val()
}
attributeArray[attributeArray.length] = temp;
})
}
}
$("#AttributeJsonObject").val(JSON.stringify(attributeArray));
var formData = $(".mainForm").serialize();
xhr({
type: "post",
url: "/events/saveFreeText/" + id,
url: "/events/saveFreeText/" + event_id,
data: formData,
success: function () {
window.location = baseurl + '/events/view/' + id;
window.location = baseurl + '/events/view/' + event_id;
},
});
}
@ -4173,27 +4143,20 @@ function loadTagTreemap() {
});
}
function quickEditEvent(id, field) {
xhr({
success:function (data) {
$("#" + field + "Field").html(data);
},
type:"get",
url: "/events/quickEdit/" + id + "/" + field,
});
}
function selectAllInbetween(last, current) {
if (last === false || last == current) return false;
var from = $('#' + last).parent().parent().index();
var to = $('#' + current).parent().parent().index();
if (last === false || last === current) {
return false;
}
var from = $(last).parent().parent().index();
var to = $(current).parent().parent().index();
if (to < from) {
var temp = from;
from = to;
to = temp;
}
$('.select_proposal, .select_attribute, .select').each(function (e) {
if ($('#' + this.id).parent().parent().index() >= from && $('#' + this.id).parent().parent().index() <= to) {
$('.select_proposal, .select_attribute, .select').each(function () {
var index = $(this).parent().parent().index();
if (index >= from && index <= to) {
$(this).prop('checked', true);
}
});
@ -4301,6 +4264,7 @@ $(function() {
$("#popover_matrix").fadeOut();
$(".loading").hide();
resetForms();
resetEditHoverForms();
})
});
@ -4310,6 +4274,7 @@ $(document).keyup(function(e){
$("#popover_matrix").fadeOut();
$(".loading").hide();
resetForms();
resetEditHoverForms();
}
});
@ -4761,9 +4726,6 @@ $(document.body).on('click', 'a[data-paginator]', function (e) {
success: function (data) {
$(paginatorTarget).html(data);
},
error: function () {
showMessage('fail', 'Could not fetch the requested data.');
},
url: $(this).attr('href'),
});
});

File diff suppressed because it is too large Load Diff