First version of the templating feature complete

- still needs some refinement, but it's feature-complete
pull/274/head^2
iglocska 2014-07-02 16:20:19 +02:00
parent 9bede8e1b4
commit 45d826a252
13 changed files with 390 additions and 134 deletions

2
.gitignore vendored
View File

@ -13,6 +13,8 @@
/app/tmp/cache/views/myapp*
/app/files/*
!/app/files/empty
/app/tmp/files/*
!/app/tmp/files/empty
/app/webroot/img/logo.png
/app/Config/bootstrap.php
/app/Config/database.php

View File

@ -1,6 +1,8 @@
<?php
App::uses('AppController', 'Controller');
App::uses('Folder', 'Utility');
App::uses('File', 'Utility');
/**
* Templates Controller
@ -20,7 +22,7 @@ class TemplatesController extends AppController {
public function beforeFilter() { // TODO REMOVE
parent::beforeFilter();
$this->Security->unlockedActions = array('saveElementSorting', 'populateEventFromTemplate');
$this->Security->unlockedActions = array('saveElementSorting', 'populateEventFromTemplate', 'uploadFile', 'deleteTemporaryFile');
}
public function fetchFormFromTemplate($id) {
@ -275,20 +277,22 @@ class TemplatesController extends AppController {
$this->set('template_id', $template_id);
$this->set('event_id', $event_id);
if ($this->request->is('post')) {
$errors = array();
$this->set('template', $this->request->data);
$result = $this->Event->Attribute->checkTemplateAttributes($template, $this->request->data, $event_id, $event['Event']['distribution']);
$errors = $result['errors'];
$attributes = $result['attributes'];
if (empty($errors) && empty($this->request->data['Template']['modify'])) {
$this->set('template', $this->request->data);
$this->set('attributes', $attributes);
$this->set('distributionLevels', $this->Event->distributionLevels);
$this->render('populate_event_from_template_attributes');
} else {
$this->set('template', $this->request->data);
$this->set('errors', $errors);
if (isset($this->request->data['Template']['modify']) || !empty($result['errors'])) {
$fileArray = $this->request->data['Template']['fileArray'];
$this->set('fileArray', $fileArray);
$this->set('errors', $result['errors']);
$this->set('templateData', $template);
$this->set('validTypeGroups', $this->Event->Attribute->validTypeGroups);
} else {
$this->set('errors', $result['errors']);
$this->set('attributes', $result['attributes']);
$fileArray = $this->request->data['Template']['fileArray'];
$this->set('fileArray', $fileArray);
$this->set('distributionLevels', $this->Event->distributionLevels);
$this->render('populate_event_from_template_attributes');
}
} else {
$this->set('templateData', $template);
@ -303,17 +307,42 @@ class TemplatesController extends AppController {
'conditions' => array('id' => $event_id),
'recursive' => -1,
'fields' => array('id', 'orgc', 'distribution'),
'contain' => 'EventTag',
));
if (empty($event)) throw new MethodNotAllowedException('Event not found or you are not authorised to edit it.');
if (!$this->_isSiteAdmin()) {
if ($event['Event']['orgc'] != $this->Auth->user('org')) throw new MethodNotAllowedException('Event not found or you are not authorised to edit it.');
}
$template = $this->Template->find('first', array(
'id' => $template_id,
'recursive' => -1,
'contain' => 'TemplateTag',
'fields' => 'id',
));
foreach ($template['TemplateTag'] as $tag) {
$exists = false;
foreach ($event['EventTag'] as $eventTag) {
if ($eventTag['tag_id'] == $tag['tag_id']) $exists = true;
}
if (!$exists) {
$this->Event->EventTag->create();
$this->Event->EventTag->save(array('event_id' => $event_id, 'tag_id' => $tag['tag_id']));
}
}
if (isset($this->request->data['Template']['attributes'])) {
$attributes = unserialize($this->request->data['Template']['attributes']);
$this->loadModel('Attribute');
$fails = 0;
foreach($attributes as $k => $attribute) {
foreach($attributes as $k => &$attribute) {
if (isset($attribute['data'])) {
$file = new File(APP . 'tmp/files/' . $attribute['data']);
$content = $file->read();
$attribute['data'] = base64_encode($content);
$file->delete();
}
$this->Attribute->create();
if (!$this->Attribute->save(array('Attribute' => $attribute))) $fails++;
}
@ -328,4 +357,65 @@ class TemplatesController extends AppController {
throw new MethodNotAllowedException();
}
}
public function uploadFile($elementId, $batch) {
$this->layout = 'iframe';
$this->set('batch', $batch);
$this->set('element_id', $elementId);
if ($this->request->is('get')) {
$this->set('element_id', $elementId);
} else if ($this->request->is('post')) {
$fileArray = array();
$filenames = array();
$tmp_names = array();
$element_ids = array();
$result = array();
$added = 0;
$failed = 0;
// filename checks
foreach ($this->request->data['Template']['file'] as $k => $file) {
if ($file['size'] > 0 && $file['error'] == 0) {
if (preg_match('@^[\w\-. ]+$@', $file['name'])) {
$fn = $this->Template->generateRandomFileName();
move_uploaded_file($file['tmp_name'], APP . 'tmp/files/' . $fn);
$filenames[] =$file['name'];
$fileArray[] = array('filename' => $file['name'], 'tmp_name' => $fn, 'element_id' => $elementId);
$added++;
} else $failed++;
} else $failed ++;
}
$result = $added . ' files uploaded.';
if ($failed) {
$result .= ' ' . $failed . ' files either failed to upload, or were empty.';
$this->set('upload_error', true);
} else {
$this->set('upload_error', false);
}
$this->set('result', $result);
$this->set('filenames', $filenames);
$this->set('fileArray', json_encode($fileArray));
}
}
private function __combineArrays($array, $array2) {
foreach ($array2 as $element) {
if (!in_array($element, $array)) {
$array[] = $element;
}
}
return $array;
}
public function deleteTemporaryFile($filename) {
if (!$this->request->is('post')) throw new MethodNotAllowedException('This action is restricted to accepting POST requests only.');
//if (!$this->request->is('ajax')) throw new MethodNotAllowedException('This action is only accessible through AJAX.');
$this->autoRender = false;
if (preg_match('/^[a-zA-Z0-9]{12}$/', $filename)) {
$file = new File(APP . 'tmp/files/' . $filename);
if ($file->exists()) {
$file->delete();
}
}
}
}

View File

@ -1361,23 +1361,27 @@ class Attribute extends AppModel {
}
public function checkTemplateAttributes($template, $data, $event_id, $distribution) {
public function checkTemplateAttributes($template, &$data, $event_id, $distribution) {
$result = array();
$errors = array();
$attributes = array();
$files = array();
$savedFiles = array();
if (isset($data['Template']['fileArray'])) $fileArray = json_decode($data['Template']['fileArray'], true);
foreach ($template['TemplateElement'] as $element) {
if ($element['element_definition'] == 'attribute') {
$result = $this->__resolveElementAttribute($element['TemplateElementAttribute'][0], $data['Template']['value_' . $element['id']]);
} else if ($element['element_definition'] == 'file') {
$temp = array();
foreach ($data['Template']['file_' . $element['id']] as $fileArray) {
foreach ($fileArray as $k => $file) {
if (($file['name'] != '' && $file['size'] > 0) || ($k + 1 == count($fileArray))) {
$temp[] = $file;
}
}
if (isset($fileArray)) {
foreach ($fileArray as $fileArrayElement) {
if ($fileArrayElement['element_id'] == $element['id']) {
$temp[] = $fileArrayElement;
}
}
}
$result = $this->__resolveElementFile($element['TemplateElementFile'][0], $temp);
if ($element['TemplateElementFile'][0]['mandatory'] && empty($temp) && empty($errors[$element['id']])) $errors[$element['id']] = 'Error: This field is mandatory.';
}
if ($element['element_definition'] == 'file' || $element['element_definition'] == 'attribute') {
if ($result['errors']) {
@ -1431,11 +1435,11 @@ class Attribute extends AppModel {
return array('attributes' => $results, 'errors' => $errors);
}
private function __resolveElementFile($element, $value) {
private function __resolveElementFile($element, $files) {
$attributes = array();
$errors = null;
$results = array();
$count = count($value);
$count = count($files);
$element['complex'] = false;
if ($element['malware']) {
$element['type'] = 'malware-sample';
@ -1444,48 +1448,41 @@ class Attribute extends AppModel {
$element['type'] = 'attachment';
$element['to_ids'] = false;
}
if ($count == 1 && $value[0]['size'] == 0) {
if ($element['mandatory']) $errors = 'This field is mandatory.';
} else {
if ($count > 1) unset($value[$count-1]);
foreach ($value as $v) {
if (!($v['size'] > 0 && $v['error'] == 0)) {
$errors = 'File upload failed or the file was empty.';
} else if (!preg_match('@^[\w\-. ]+$@', $v['name'])) {
$errors = 'Filename not allowed.';
} else {
if ($element['malware']) {
$malwareName = $v['name'] . '|' . hash_file('md5', $v['tmp_name']);
$attributes[] = $this->__createAttribute($element, $malwareName);
$file = new File($v['tmp_name']);
if (!$file->exists()) {
$errors = 'File cannot be read.';
} else {
$content = $file->read();
$attributes[count($attributes) - 1]['data'] = base64_encode($content);
$element['type'] = 'filename|sha256';
$sha256 = $v['name'] . '|' . (hash_file('sha256', $v['tmp_name']));
$attributes[] = $this->__createAttribute($element, $sha256);
$element['type'] = 'filename|sha1';
$sha1 = $v['name'] . '|' . (hash_file('sha1', $v['tmp_name']));
$attributes[] = $this->__createAttribute($element, $sha1);
}
} else {
$attributes[] = $this->__createAttribute($element, $v['name']);
$file = new File($v['tmp_name']);
if (!$file->exists()) {
$errors = 'File cannot be read.';
} else {
$content = $file->read();
$attributes[count($attributes) - 1]['data'] = base64_encode($content);
}
}
}
}
foreach ($files as $file) {
if (!preg_match('@^[\w\-. ]+$@', $file['filename'])) {
$errors = 'Filename not allowed.';
continue;
}
if ($element['malware']) {
$malwareName = $file['filename'] . '|' . hash_file('md5', APP . 'tmp/files/' . $file['tmp_name']);
$tmp_file = new File(APP . 'tmp/files/' . $file['tmp_name']);
if (!$tmp_file->exists()) {
$errors = 'File cannot be read.';
} else {
$attributes[] = $this->__createAttribute($element, $malwareName);
$content = $tmp_file->read();
$attributes[count($attributes) - 1]['data'] = $file['tmp_name'];
$element['type'] = 'filename|sha256';
$sha256 = $file['filename'] . '|' . (hash_file('sha256', APP . 'tmp/files/' . $file['tmp_name']));
$attributes[] = $this->__createAttribute($element, $sha256);
$element['type'] = 'filename|sha1';
$sha1 = $file['filename'] . '|' . (hash_file('sha1', APP . 'tmp/files/' . $file['tmp_name']));
$attributes[] = $this->__createAttribute($element, $sha1);
}
} else {
$attributes[] = $this->__createAttribute($element, $file['filename']);
$tmp_file = new File(APP . 'tmp/files/' . $file['tmp_name']);
if (!$tmp_file->exists()) {
$errors = 'File cannot be read.';
} else {
$content = $tmp_file->read();
$attributes[count($attributes) - 1]['data'] = $file['tmp_name'];
}
}
}
return array('attributes' => $attributes, 'errors' => $errors);
return array('attributes' => $attributes, 'errors' => $errors, 'files' => $files);
}
private function __createAttribute($element, $value) {
$attribute = array(
'comment' => $element['name'],

View File

@ -1150,45 +1150,46 @@ class Event extends AppModel {
// But only do this if it is allowed in the bootstrap.php file.
//
if ($eventIsPrivate) {
$conditions = array('User.autoalert' => 1, 'User.gpgkey =' => "", 'User.org =' => $event['Event']['org']);
$conditions = array('User.autoalert' => 1, 'User.gpgkey =' => "", 'User.org =' => $event['Event']['org']);
} else {
$conditions = array('User.autoalert' => 1, 'User.gpgkey =' => "");
$conditions = array('User.autoalert' => 1, 'User.gpgkey =' => "");
}
if ('false' == Configure::read('GnuPG.onlyencrypted')) {
$alertUsers = $this->User->find('all', array(
'conditions' => $conditions,
'recursive' => 0,
));
$max = count($alertUsers);
foreach ($alertUsers as $k => &$user) {
// prepare the the unencrypted email
$Email = new CakeEmail();
$Email->from(Configure::read('MISP.email'));
$Email->to($user['User']['email']);
$Email->subject("[" . Configure::read('MISP.org') . " " . Configure::read('MISP.name') . "] Event " . $id . " - " . $subject . $event['ThreatLevel']['name'] . " - TLP Amber");
$Email->emailFormat('text'); // both text or html
// send it
$Email->send($bodySigned);
$Email->reset();
if ($processId) {
$this->Job->id = $processId;
$this->Job->saveField('progress', $k / $max * 50);
}
if ('false' == Configure::read('GnuPG.onlyencrypted')) {
$alertUsers = $this->User->find('all', array(
'conditions' => $conditions,
'recursive' => 0,
));
$max = count($alertUsers);
foreach ($alertUsers as $k => &$user) {
// prepare the the unencrypted email
$Email = new CakeEmail();
$Email->from(Configure::read('MISP.email'));
$Email->to($user['User']['email']);
$Email->subject("[" . Configure::read('MISP.org') . " " . Configure::read('MISP.name') . "] Event " . $id . " - " . $subject . $event['ThreatLevel']['name'] . " - TLP Amber");
$Email->emailFormat('text'); // both text or html
// send it
$Email->send($bodySigned);
$Email->reset();
if ($processId) {
$this->Job->id = $processId;
$this->Job->saveField('progress', $k / $max * 50);
}
}
//
// Build a list of the recipients that wish to receive encrypted mails.
//
if ($eventIsPrivate) {
$conditions = array('User.autoalert' => 1, 'User.gpgkey !=' => "", 'User.org =' => $event['Event']['org']);
} else {
$conditions = array('User.autoalert' => 1, 'User.gpgkey !=' => "");
}
$alertUsers = $this->User->find('all', array(
'conditions' => $conditions,
'recursive' => 0,
)
);
}
//
// Build a list of the recipients that wish to receive encrypted mails.
//
if ($eventIsPrivate) {
$conditions = array('User.autoalert' => 1, 'User.gpgkey !=' => "", 'User.org =' => $event['Event']['org']);
} else {
$conditions = array('User.autoalert' => 1, 'User.gpgkey !=' => "");
}
$alertUsers = $this->User->find('all', array(
'conditions' => $conditions,
'recursive' => 0,
)
);
$max = count($alertUsers);
// encrypt the mail for each user and send it separately
foreach ($alertUsers as $k => &$user) {
// send the email

View File

@ -65,4 +65,15 @@ class Template extends AppModel {
return false;
}
}
public function generateRandomFileName() {
$length = 12;
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charLen = strlen($characters) - 1;
$fn = '';
for ($p = 0; $p < $length; $p++) {
$fn .= $characters[rand(0, $charLen)];
}
return $fn;
}
}

View File

@ -1,25 +1,30 @@
<?php //debug($element_id); ?>
<div id="populate_template_info" class="templateTableRow templateTableRow80">
<div class="templateElementHeader" style="width:100%; position:relative;">
<div class="templateGlass"></div>
<div class ="templateElementHeaderText"><?php echo h($element['name']); ?></div>
<div class ="templateElementHeaderText">
<?php echo h($element['name']);
if ($element['mandatory']): ?>
<span class="template_mandatory">(*)</span>
<?php endif;?>
</div>
</div>
<div id="populate_template_info_body" class="populate_template_div_body">
<div class="left">Description:</div>
<div class="right"><?php echo h($element['description']); ?></div><br />
<div class="left">File<?php if ($element['batch']) echo 's'?>:</div>
<div class="right" id ="filenames_<?php echo $element_id; ?>">&nbsp;</div><br />
<div class="left" style="height:26px;">File<?php if ($element['batch']) echo 's'?>:</div>
<div class="right" id ="filenames_<?php echo $element_id; ?>" style="height:26px;">
&nbsp;
</div><br />
<div class="input file" id="file_container_<?php echo $element_id;?>">
</div>
<iframe id="iframe_<?php echo $element_id; ?>" src="/templates/uploadFile/<?php echo $element_id; ?>/<?php echo ($element['batch'] ? 'yes' : 'no'); ?>" style="border:0px;height:30px;width:100%;overflow:hidden;" scrolling="no"></iframe>
<div class="error-message populateTemplateErrorField" <?php if(!isset($errors[$element_id])) echo 'style="display:none;"';?>>
<?php echo 'Error: ' . $errors[$element_id]; ?>
</div>
</div>
</div>
<script type="text/javascript">
var i_<?php echo $element_id; ?> = 0;
var element_id_<?php echo $element_id; ?> = <?php echo $element_id; ?>;
var batch_<?php echo $element_id; ?> = "<?php echo ($element['batch'] ? 'yes' : 'no'); ?>";
$(document).ready(function() {
populateTemplateCreateFileUpload(element_id_<?php echo $element_id; ?>, i_<?php echo $element_id; ?>, batch_<?php echo $element_id; ?>);
});
var i_<?php echo $element_id; ?> = 0;
var element_id_<?php echo $element_id; ?> = <?php echo $element_id; ?>;
var batch_<?php echo $element_id; ?> = "<?php echo ($element['batch'] ? 'yes' : 'no'); ?>";
</script>

View File

@ -0,0 +1,23 @@
<?php
/**
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package Cake.View.Layouts
* @since CakePHP(tm) v 0.10.0.1076
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
?>
<?php
echo $this->Html->css('bootstrap');
echo $this->Html->css('main');
echo $this->Html->script('jquery-2.1.0.min');
echo $content_for_layout; ?>

View File

@ -11,6 +11,11 @@
foreach ($templateData['TemplateElement'] as $k => $element) {
echo $this->element('templateElements/populateTemplate' . ucfirst($element['element_definition']), array('element' => $element['TemplateElement' . ucfirst($element['element_definition'])][0], 'k' => $k, 'element_id' => $element['id'], 'value' => ''));
}
echo $this->Form->input('fileArray', array(
'label' => false,
'style' => 'display:none;',
'value' => '[]',
));
?>
</fieldset>
<?php
@ -18,3 +23,11 @@ echo $this->Form->button('Add', array('class' => 'btn btn-primary'));
echo $this->Form->end();
?>
</div>
<script type="text/javascript">
$(document).ready(function() {
<?php if (isset($fileArray)): ?>
populateTemplateHiddenFileDiv(<?php echo $fileArray; ?>);
<?php endif; ?>
populateTemplateFileBubbles();
});
</script>

View File

@ -56,6 +56,16 @@ endforeach;?>
'type' => 'hidden',
'value' => true,
));
echo $this->Form->input('errors', array(
'label' => false,
'type' => 'hidden',
'value' => serialize($errors),
));
echo $this->Form->input('fileArray', array(
'label' => false,
'type' => 'hidden',
'value' => $fileArray,
));
?>
</fieldset>
<?php

View File

@ -0,0 +1,4 @@
<?php
echo $this->Form->create('', array('type' => 'file'));
echo $this->Form->end();
?>

View File

@ -0,0 +1,32 @@
<?php
echo $this->Html->script('ajaxification');
if ($batch == 'yes') {
$buttonText = 'Upload Files';
$multiple = true;
} else {
$multiple = false;
if (isset($filenames)) {
$buttonText = 'Replace File';
} else {
$buttonText = 'Upload File';
}
}
?>
<div style="display:none;">
<?php
echo $this->Form->create('', array('id' => 'upload_' . $element_id, 'type' => 'file'));
echo $this->Form->input('file.', array('id' => 'upload_' . $element_id . '_file', 'type' => 'file', 'label' => false, 'multiple' => $multiple, 'onChange' => 'this.form.submit()'));
echo $this->Form->end();
?>
</div>
<span id="fileUploadButton_<?php echo $element_id; ?>" class="btn btn-primary" onClick="templateFileUploadTriggerBrowse('<?php echo $element_id; ?>');"><?php echo $buttonText; ?></span>
<script type="text/javascript">
$(document).ready(function() {
<?php if (isset($filenames)): ?>
var fileArray = JSON.parse('<?php echo $fileArray;?>');
templateFileHiddenAdd(fileArray, '<?php echo $element_id; ?>', '<?php echo $batch; ?>');
showMessage('<?php echo $upload_error ? 'fail' : 'success'; ?>', '<?php echo $result; ?>', 'iframe');
<?php endif; ?>
});
</script>

0
app/tmp/files/empty Normal file
View File

View File

@ -297,7 +297,6 @@ function deleteSelectedAttributes(event) {
});
$('#AttributeIds').attr('value', JSON.stringify(selected));
var formData = $('#delete_selected').serialize();
console.log(formData);
$.ajax({
data: formData,
cache: false,
@ -503,7 +502,6 @@ function recoverValuesFromPersistance(formPersistanceArray) {
function handleValidationErrors(responseArray, context, contextNamingConvention) {
for (var k in responseArray) {
var elementName = k.charAt(0).toUpperCase() + k.slice(1);
console.log("#" + contextNamingConvention + elementName);
$("#" + contextNamingConvention + elementName).parent().addClass("error");
$("#" + contextNamingConvention + elementName).parent().append("<div class=\"error-message\">" + responseArray[k] + "</div>");
}
@ -536,7 +534,13 @@ function updateHistogram(selected) {
});
}
function showMessage(success, message) {
function showMessage(success, message, context) {
if (typeof context !== "undefined") {
$("#ajax_" + success, window.parent.document).html(message);
var duration = 1000 + (message.length * 40);
$("#ajax_" + success + "_container", window.parent.document).fadeIn("slow");
$("#ajax_" + success + "_container", window.parent.document).delay(duration).fadeOut("slow");
}
$("#ajax_" + success).html(message);
var duration = 1000 + (message.length * 40);
$("#ajax_" + success + "_container").fadeIn("slow");
@ -758,33 +762,97 @@ function getTemplateChoicePopup(id) {
function resizePopoverBody() {
var bodyheight = $(window).height();
bodyheight = 3 * bodyheight / 4 - 150;
console.log(bodyheight);
$("#popover_choice_main").css({"max-height": bodyheight});
}
function populateTemplateHiddenFileDiv(files) {
$('#TemplateFileArray').val(JSON.stringify(files));
}
function populateTemplateBindChangeEvent(name, filenameContainer, e, i, batch) {
$(name).change(
function(){
if (batch == 'yes') {
var files = $(this)[0].files;
for (var i = 0; i < files.length; i++) {
$(filenameContainer).append('<div class ="template_file_box_container"><span class="tagFirstHalf template_file_box">' + files[i].name + '</span><span class="tagSecondHalf useCursorPointer">x</span></div>');
}
$(name).hide();
i++;
populateTemplateCreateFileUpload(e, i, batch);
} else {
$(filenameContainer).html('<span class="tagFirstHalf">' + $(this).val() + '<span class="icon-remove"></span></span>');
}
function populateTemplateFileBubbles() {
var fileObjectArray = JSON.parse($('#TemplateFileArray').val());
fileObjectArray.forEach(function(entry) {
templateAddFileBubble(entry.element_id, false, entry.filename, entry.tmp_name, 'yes');
});
}
function populateTemplateCreateFileUpload(e, i, batch) {
if (batch == 'yes') {
$('#file_container_' + e).append('<input id="Template' + e + 'File' + i + '" type="file" name="data[Template][file_' + e + '][' + i + '][]" multiple="multiple">');
} else {
$('#file_container_' + e).append('<input id="Template' + e + 'File' + i + '" type="file" name="data[Template][file_' + e + '][' + i + '][]">');
function templateFileHiddenAdd(files, element_id, batch) {
var fileArray = $.parseJSON($('#TemplateFileArray', window.parent.document).val());
var contained = false;
for (var j=0; j< files.length; j++) {
for (var i=0; i< fileArray.length; i++) {
if (fileArray[i].filename == files[j].filename) {
contained = true;
}
if (batch == 'no' && fileArray[i].element_id == element_id) {
templateDeleteFileBubble(fileArray[i].filename, fileArray[i].tmp_name, fileArray[i].element_id, 'iframe', batch);
contained = false;
var removeId = i;
}
}
if (batch == 'no') fileArray.splice(removeId, 1);
if (contained == false) {
fileArray.push(files[j]);
templateAddFileBubble(element_id, true, files[j].filename, files[j].tmp_name, batch);
$('#TemplateFileArray', window.parent.document).val(JSON.stringify(fileArray));
}
}
populateTemplateBindChangeEvent('#Template' + e + 'File' + i, '#filenames_' + e, e, i, batch);
}
}
function templateAddFileBubble(element_id, iframe, filename, tmp_name, batch) {
if (batch == 'no') {
if (iframe == true) {
$('#filenames_' + element_id, window.parent.document).html('<div id ="' + tmp_name + '_container" class ="template_file_box_container"><span class="tagFirstHalf template_file_box">' + filename + '</span><span onClick="templateDeleteFileBubble(\'' + filename + '\', \'' + tmp_name + '\', \'' + element_id + '\', \'normal\', \'no\');" class="tagSecondHalf useCursorPointer">x</span></div>');
} else {
$('#filenames_' + element_id).html('<div id ="' + tmp_name + '_container" class ="template_file_box_container"><span class="tagFirstHalf template_file_box">' + filename + '</span><span onClick="templateDeleteFileBubble(\'' + filename + '\', \'' + tmp_name + '\', \'' + element_id + '\', \'normal\', \'no\');" class="tagSecondHalf useCursorPointer">x</span></div>');
}
} else {
if (iframe == true) {
$('#filenames_' + element_id, window.parent.document).append('<div id ="' + tmp_name + '_container" class ="template_file_box_container"><span class="tagFirstHalf template_file_box">' + filename + '</span><span onClick="templateDeleteFileBubble(\'' + filename + '\', \'' + tmp_name + '\', \'' + element_id + '\', \'normal\', \'yes\');" class="tagSecondHalf useCursorPointer">x</span></div>');
} else {
$('#filenames_' + element_id).append('<div id ="' + tmp_name + '_container" class ="template_file_box_container"><span class="tagFirstHalf template_file_box">' + filename + '</span><span onClick="templateDeleteFileBubble(\'' + filename + '\', \'' + tmp_name + '\', \'' + element_id + '\', \'normal\', \'yes\');" class="tagSecondHalf useCursorPointer">x</span></div>');
}
}
}
function templateDeleteFileBubble(filename, tmp_name, element_id, context, batch) {
$(".loading").show();
$.ajax({
type:"post",
cache: false,
url:"/templates/deleteTemporaryFile/" + tmp_name,
});
var c = this;
if (context == 'iframe') {
$('#' + tmp_name + '_container', window.parent.document).remove();
var oldArray = JSON.parse($('#TemplateFileArray', window.parent.document).val());
} else {
$('#' + tmp_name + '_container').remove();
var oldArray = JSON.parse($('#TemplateFileArray').val());
}
var newArray = [];
oldArray.forEach(function(entry) {
if (batch == 'no') {
if (entry.element_id != element_id) {
newArray.push(entry);
}
} else {
if (entry.tmp_name != tmp_name) {
newArray.push(entry);
}
}
});
if (batch == 'no') {
$('#fileUploadButton_' + element_id, $('#iframe_' + element_id).contents()).html('Upload File');
}
if (context == 'iframe') {
$('#TemplateFileArray', window.parent.document).val(JSON.stringify(newArray));
} else {
$('#TemplateFileArray').val(JSON.stringify(newArray));
}
$(".loading").hide();
}
function templateFileUploadTriggerBrowse(id) {
$('#upload_' + id + '_file').click();
}