diff --git a/application/forms/MibForm.php b/application/forms/MibForm.php index 9166d04..b5df6b9 100644 --- a/application/forms/MibForm.php +++ b/application/forms/MibForm.php @@ -3,33 +3,40 @@ namespace Icinga\Module\Snmp\Forms; use Exception; +use Icinga\Application\Icinga; use Icinga\Authentication\Auth; +use Icinga\Exception\IcingaException; use Icinga\Module\Director\Web\Form\QuickForm; use Icinga\Module\Snmp\MibParser; use Icinga\Module\Snmp\MibUpload; +use Icinga\Web\Notification; class MibForm extends QuickForm { - protected $db; + private $db; - protected $mibSource; + private $failed = false; - protected $parsedMib; + private $fileCount = 0; public function setup() { $this->setAttrib('enctype', 'multipart/form-data'); + require_once Icinga::app() + ->getModuleManager() + ->getModule('director') + ->getApplicationDir() . '/views/helpers/FormSimpleNote.php'; + $this->addHtml('
'); + $this->addElement('file', 'uploaded_file', [ - 'label' => $this->translate('File'), + 'label' => $this->translate('Choose file'), 'destination' => $this->getTempDir(), - 'required' => true, + 'valueDisabled' => true, + 'isArray' => true, + 'multiple' => true, ]); - /** @var \Zend_Form_Element_File $el */ - $el = $this->getElement('uploaded_file'); - $el->setValueDisabled(true); - $this->setSubmitLabel($this->translate('Upload')); } @@ -39,8 +46,81 @@ protected function getTempDir() } protected function processUploadedSource() + { + if (! array_key_exists('uploaded_file', $_FILES)) { + throw new IcingaException('Got no file'); + } + + foreach ($_FILES['uploaded_file']['tmp_name'] as $key => $tmpFile) { + $originalFilename = $_FILES['uploaded_file']['name'][$key]; + + $source = file_get_contents($tmpFile); + unlink($tmpFile); + try { + $parsed = MibParser::parseString($source); + } catch (Exception $e) { + $this->addError($originalFilename . ' failed: ' . $e->getMessage()); + Notification::error($originalFilename . ' failed: ' . $e->getMessage()); + $this->failed = true; + continue; + } + if (empty($parsed)) { + Notification::error('Could not parse ' . $originalFilename); + $this->addError('Could not parse ' . $originalFilename); + $this->failed = true; + continue; + } + + $this->fileCount++; + // $this->addError(' Missing: ' . implode(', ', array_keys((array) $parsed->imports))); + MibUpload::create([ + 'username' => Auth::getInstance()->getUser()->getUsername(), + 'client_ip' => $_SERVER['REMOTE_ADDR'], + 'mib_name' => $parsed->name, + 'imports_from' => json_encode(array_keys((array) $parsed->imports)), + 'original_filename' => $originalFilename, + 'raw_mib_file' => $source, + 'parsed_mib' => json_encode($parsed), + ])->store($this->db); + } + + return true; + } + + public function onRequest() + { + if ($this->hasBeenSent()) { + try { + $this->processUploadedSource(); + } catch (Exception $e) { + $this->addError($e->getMessage()); + return; + } + + if ($this->fileCount > 0) { + if ($this->fileCount === 1) { + $this->redirectOnSuccess('New MIB file has been enqueued'); + } else { + $this->redirectOnSuccess(sprintf('%d MIB files have been enqueued', $this->fileCount)); + } + } + } + } + + public function onSuccess() + { + } + + public function setDb($db) + { + $this->db = $db; + return $this; + } + + protected function invalidProcess() { /** @var \Zend_Form_Element_File $el */ + /* $el = $this->getElement('uploaded_file'); $originalFilename = $el->getValue(); @@ -53,6 +133,14 @@ protected function processUploadedSource() $el->addFilter('Rename', $tmpFile); if ($el->receive()) { + var_dump($tmpFile); + exit; + if (! MibParser::preValidateFile($tmpFile)) { + throw new IcingaException( + 'MIB file validation failed: %s', + str_replace($tmpFile, $originalFilename, MibParser::getLastValidationError()) + ); + } $source = file_get_contents($tmpFile); unlink($tmpFile); $parsed = MibParser::parseString($source); @@ -73,25 +161,6 @@ protected function processUploadedSource() } } } - - return $this; - } - - public function onSuccess() - { - try { - $this->processUploadedSource(); - } catch (Exception $e) { - $this->addError($e->getMessage()); - - return; - } - $this->redirectOnSuccess('New MIB file has been enqueued'); - } - - public function setDb($db) - { - $this->db = $db; - return $this; + */ } } diff --git a/public/css/module.less b/public/css/module.less index 954ea18..f0f8a79 100644 --- a/public/css/module.less +++ b/public/css/module.less @@ -86,6 +86,10 @@ input[type=checkbox] { padding: 0.2em; } +input[type=file] { + visibility: hidden; +} + input[type=checkbox]:focus { border-color: @icinga-blue; } @@ -98,3 +102,26 @@ input[type=checkbox]:before { input[type=checkbox]:checked:before { content: '\e803'; } + +.mib-drop-zone { + width: 36em; + height: 16em; + border: 0.5em dashed @icinga-blue; + -webkit-border-radius: 1em; + -moz-border-radius: 1em; + border-radius: 1em; +} + +.mib-drop-zone.is-dragover { + background-color: @gray-light; +} + +.mib-drop-zone::before { + font-family: 'ifont'; + color: @icinga-blue; + content: '\e808'; + top: 1em; + position: relative; + padding-left: 3em; + font-size: 5em; +} \ No newline at end of file diff --git a/public/js/module.js b/public/js/module.js new file mode 100644 index 0000000..295427b --- /dev/null +++ b/public/js/module.js @@ -0,0 +1,118 @@ + +(function(Icinga) { + + var Snmp = function(module) { + this.module = module; + + this.initialize(); + + this.module.icinga.logger.debug('Snmp module loaded'); + }; + + Snmp.prototype = { + initialize: function() + { + this.module.on('rendered', this.rendered); + // this.module.on('change', '.mib-drop-zone', this.droppedFiles); + // this.module.on('drop', '.mib-drop-zone', this.droppedFiles); + }, + + rendered: function (event) { + $container = $(event.currentTarget); + if (this.isAdvancedUpload()) { + this.initializeFiles($container); + $container.find('.mib-drop-zone').on('change', this.droppedFiles); + } else { + $container.find('.mib-drop-zone').remove(); + } + }, + + initializeFiles: function ($container) { + var droppedFiles = false; + var $dropZone = $container.find('.mib-drop-zone'); + var $form = $dropZone.closest('form'); + + $dropZone.on('drag dragstart dragend dragover dragenter dragleave drop', function(e) { + e.preventDefault(); + e.stopPropagation(); + }) + .on('dragover dragenter', function() { + $dropZone.addClass('is-dragover'); + }) + .on('dragleave dragend drop', function() { + $dropZone.removeClass('is-dragover'); + }) + .on('drop', function(e) { + droppedFiles = e.originalEvent.dataTransfer.files; + //console.log(droppedFiles); + var $input = $form.find('input[type="file"]'); + $input.prop('files', droppedFiles); + $form.submit(); + return; + var ajaxData = new FormData($form.get(0)); +/* + if (droppedFiles) { + $.each( droppedFiles, function(i, file) { + ajaxData.append( $input.attr('name'), file ); + }); + } +*/ + $.ajax({ + url: $form.attr('action'), + type: $form.attr('method'), + data: ajaxData, + dataType: 'json', + cache: false, + contentType: false, + processData: false, + complete: function() { + $form.removeClass('is-uploading'); + }, + success: function(data) { + $dropZone.addClass( data.success === true ? 'is-success' : 'is-error' ); + if (!data.success) $errorMsg.text(data.error); + }, + error: function() { + // Log the error, show an alert, whatever works for you + } + }); + + }); + + }, + + isAdvancedUpload: function () { + var div = document.createElement('div'); + return (('draggable' in div) + || ('ondragstart' in div && 'ondrop' in div)) + && 'FormData' in window && 'FileReader' in window; + }, + + droppedFiles: function(event){ + console.log('Triggered'); + event.preventDefault(); + event.stopPropagation(); + var files = event.target.files; + $('#drop').css('display', 'none'); + for(var i = 0, len = files.length; i < len; i++) { + if(files[i].type === 'text/plain' || files[i].type === ''){ + $.ajax({ + type: "POST", + url: "uploader.php?id="+i, + contentType: "multipart/form-data", + headers: { + "X-File-Name" : files[i].name, + "X-File-Size" : files[i].size, + "X-File-Type" : files[i].type + } + }); + }else{ + $('#info').append('Content type must be text/plain'); + } + } + } + }; + + Icinga.availableModules.snmp = Snmp; + +}(Icinga));