Fixed an issue with the free-text import failing on more than ~100 parsed values, fixes #389

- Caused by a 1k variable / form limit imposed by php since 5.3.9
- Form data now collected by JS and passed as a single JSON in the POST request
- Allows massive IOC lists to be imported
- improved performance
pull/400/head
iglocska 2015-02-10 14:42:24 +01:00
parent d89a266c85
commit 701160acd9
3 changed files with 105 additions and 62 deletions

View File

@ -2860,24 +2860,23 @@ class EventsController extends AppController {
if (!$this->_isSiteAdmin() && !empty($event) && $event['Event']['orgc'] != $this->Auth->user('org')) throw new MethodNotAllowedException('Event not found or you don\'t have permissions to create attributes');
$saved = 0;
$failed = 0;
foreach ($this->request->data['Attribute'] as $k => $attribute) {
if ($attribute['save'] == '1') {
if ($attribute['type'] == 'ip-src/ip-dst') {
$types = array('ip-src', 'ip-dst');
$attributes = json_decode($this->request->data['Attribute']['JsonObject'], true);
foreach ($attributes as $k => $attribute) {
if ($attribute['type'] == 'ip-src/ip-dst') {
$types = array('ip-src', 'ip-dst');
} else {
$types = array($attribute['type']);
}
foreach ($types as $type) {
$this->Event->Attribute->create();
$attribute['type'] = $type;
$attribute['distribution'] = $event['Event']['distribution'];
if (empty($attribute['comment'])) $attribute['comment'] = 'Imported via the freetext import.';
$attribute['event_id'] = $id;
if ($this->Event->Attribute->save($attribute)) {
$saved++;
} else {
$types = array($attribute['type']);
}
foreach ($types as $type) {
$this->Event->Attribute->create();
$attribute['type'] = $type;
$attribute['distribution'] = $event['Event']['distribution'];
if (empty($attribute['comment'])) $attribute['comment'] = 'Imported via the freetext import.';
$attribute['event_id'] = $id;
if ($this->Event->Attribute->save($attribute)) {
$saved++;
} else {
$failed++;
}
$failed++;
}
}
}

View File

@ -1,6 +1,16 @@
<div class="index">
<h2>Freetext Import Results</h2>
<p>Below you can see the attributes that are to be created based on the results of the free-text import. Make sure that the categories and the types are correct, often several options will be offered based on an inconclusive automatic resolution. </p>
<?php
echo $this->Form->create('Attribute', array('url' => '/events/saveFreeText/' . $event_id));
echo $this->Form->input('JsonObject', array(
'label' => false,
'type' => 'text',
'style' => 'display:none;',
'value' => '',
));
echo $this->Form->end();
?>
<table class="table table-striped table-hover table-condensed">
<tr>
<th>Value</th>
@ -12,23 +22,25 @@
</tr>
<?php
$options = array();
echo $this->Form->create('Attribute', array('url' => '/events/saveFreeText/' . $event_id));
foreach ($resultArray as $k => $item):
?>
<tr id="row_<?php echo $k; ?>" class="freetext_row">
<?php
echo $this->Form->input('Attribute.' . $k . '.save', array(
echo $this->Form->input('Attribute' . $k . 'Save', array(
'label' => false,
'style' => 'display:none;',
'value' => 1,
));
echo $this->Form->input('Attribute.' . $k . '.value', array(
echo $this->Form->input('Attribute' . $k . 'Value', array(
'label' => false,
'type' => 'hidden',
'value' => h($item['value']),
));
?>
<td><?php echo h($item['value']); ?></td>
<td>
<input type="hidden" id="<?php echo 'Attribute' . $k . 'Save'; ?>" value=1 >
<div id="<?php echo 'Attribute' . $k . 'Value'; ?>"><?php echo h($item['value']); ?></div>
</td>
<td class="short">
<?php
if (!isset($item['category'])) {
@ -36,53 +48,43 @@
} else {
$default = array_search($item['category'], $typeCategoryMapping[$item['default_type']]);
}
echo $this->Form->input('Attribute.' . $k . '.category', array(
'label' => false,
'style' => 'padding:0px;height:20px;margin-bottom:0px;',
'options' => $typeCategoryMapping[$item['default_type']],
'value' => $default,
));
?>
<select id="<?php echo 'Attribute' . $k . 'Category'; ?>" style='padding:0px;height:20px;margin-bottom:0px;'>
<?php
foreach ($typeCategoryMapping[$item['default_type']] as $type) {
echo '<option value="' . $type . '" ';
if ($type == $default) echo 'selected="selected"';
echo '>' . $type . '</option>';
}
?>
</select>
</td>
<td class="short">
<?php
$divVisibility = '';
$selectVisibility = '';
if (count($item['types']) == 1) {
echo h($item['default_type']);
echo $this->Form->input('Attribute.' . $k . '.type', array(
'label' => false,
'type' => 'hidden',
'value' => $item['default_type'],
));
$selectVisibility = 'display:none;';
} else {
echo $this->Form->input('Attribute.' . $k . '.type', array(
'label' => false,
'style' => 'padding:0px;height:20px;margin-bottom:0px;',
'options' => $item['types'],
'value' => $item['default_type'],
'class' => 'typeToggle',
));
if (!in_array(array_keys($item['types']), $options)) $options[] = array_keys($item['types']);
$divVisibility = 'style="display:none;"';
if (!in_array(array_keys($item['types']), $options)) $options[] = array_keys($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; ?>'>
<?php
foreach ($item['types'] as $type) {
echo '<option value="' . $type . '" ';
echo ($type == $item['default_type'] ? 'selected="selected"' : '') . '>' . $type . '</option>';
}
?>
</select>
</td>
<td class="short" style="width:30px;">
<?php
echo $this->Form->input('Attribute.' . $k . '.to_ids', array(
'label' => false,
'type' => 'checkbox',
'checked' => $item['to_ids'],
));
?>
<input type="checkbox" id="<?php echo 'Attribute' . $k . 'To_ids'; ?>" <?php if ($item['to_ids']) echo 'checked'; ?>/>
</td>
<td class="short">
<?php
echo $this->Form->input('Attribute.' . $k . '.comment', array(
'label' => false,
'style' => 'padding:0px;height:20px;margin-bottom:0px;',
'type' => 'text',
'placeholder' => 'Imported via the freetext import.',
));
?>
<input type="text" id="<?php echo 'Attribute' . $k . 'Comment'; ?>" style="padding:0px;height:20px;margin-bottom:0px;" placeholder="Imported via the freetext import." />
</td>
<td class="action short">
<span class="icon-remove pointer" onClick="freetextRemoveRow('<?php echo $k; ?>', '<?php echo $event_id; ?>');"></span>
@ -101,9 +103,8 @@
}
?>
</table>
<button class="btn btn-primary" onClick="freetextImportResultsSubmit('<?php echo h($event_id); ?>', '<?php echo count($resultArray); ?>');">Submit</button>
<?php
echo $this->Form->button('Submit', array('class' => 'btn btn-primary'));
echo $this->Form->end();
if (!empty($optionsRearranged)):
?>
<span style="float:right">

View File

@ -1292,13 +1292,22 @@ function changeFreetextImportExecute() {
var to = $('#changeTo').val();
$('.typeToggle').each(function() {
if ($( this ).val() == from) {
if ($('#' + $(this).attr('id') + " option[value='" + from + "']").length > 0) {
$( this ).val(to);
}
if (selectContainsOption("#" + $(this).attr('id'), to)) $( this ).val(to);
}
});
}
function selectContainsOption(selectid, value) {
var exists = false;
$(selectid + ' option').each(function(){
if (this.value == value) {
exists = true;
return false;
}
});
return exists;
}
function exportChoiceSelect(url, elementId, checkbox) {
if (checkbox == 1) {
if ($('#' + elementId + '_toggle').prop('checked')) {
@ -1306,4 +1315,38 @@ function exportChoiceSelect(url, elementId, checkbox) {
}
}
document.location.href = url;
}
}
function freetextImportResultsSubmit(id, count) {
var attributeArray = [];
var temp;
for (i = 0; i < count; i++) {
if ($('#Attribute' + i + 'Save').val() == 1) {
temp = {
value:$('#Attribute' + i + 'Value').val(),
category:$('#Attribute' + i + 'Category').val(),
type:$('#Attribute' + i + 'Type').val(),
to_ids:$('#Attribute' + i + 'To_ids')[0].checked,
comment:$('#Attribute' + i + 'Comment').val(),
}
attributeArray[attributeArray.length] = temp;
}
}
$("#AttributeJsonObject").val(JSON.stringify(attributeArray));
var formData = $("#AttributeFreeTextImportForm").serialize();
$.ajax({
type: "post",
cache: false,
url: "/events/saveFreeText/" + id,
data: formData,
beforeSend: function (XMLHttpRequest) {
$(".loading").show();
},
success:function (data, textStatus) {
window.location = '/events/view/' + id;
},
complete:function() {
$(".loading").hide();
},
});
}