From 19a669fe0433cac2627a5d843785cf1c097faed7 Mon Sep 17 00:00:00 2001 From: Jurriaan Bremer Date: Thu, 6 Apr 2017 10:32:27 +0200 Subject: [PATCH] revert integration of lightbox into bower due to incompatable versions And while at it also replace some /img/ paths with /images/ etc. --- cuckoo/web/src/assets.json | 6 +- cuckoo/web/src/bower.json | 1 - cuckoo/web/src/scss/plugins/_jstree.scss | 2 +- cuckoo/web/static/css/lightbox.css | 205 +++++++++++ cuckoo/web/static/css/main.css | 2 +- cuckoo/web/static/css/vendor.css | 36 -- cuckoo/web/static/js/misc/lightbox.js | 411 +++++++++++++++++++++++ cuckoo/web/templates/footer.html | 1 + cuckoo/web/templates/header.html | 1 + 9 files changed, 622 insertions(+), 43 deletions(-) create mode 100644 cuckoo/web/static/css/lightbox.css create mode 100644 cuckoo/web/static/js/misc/lightbox.js diff --git a/cuckoo/web/src/assets.json b/cuckoo/web/src/assets.json index 54360c533b..77421d851d 100644 --- a/cuckoo/web/src/assets.json +++ b/cuckoo/web/src/assets.json @@ -12,15 +12,13 @@ "handlebars/handlebars.js", "string/dist/string.js", "moment/moment.js", - "chart.js/dist/Chart.js", - "lightbox2/dist/lightbox.js" + "chart.js/dist/Chart.js" ], "css/vendor.css@concat": [ "font-roboto/dist/styles/roboto.css", "bootstrap/dist/css/bootstrap.css", "highlight/src/styles/default.css", - "datatables/media/src/dataTables.bootstrap.css", - "lightbox2/dist/css/lightbox.css" + "datatables/media/src/dataTables.bootstrap.css" ], "fonts@copy": [ "font-awesome/fonts/*", diff --git a/cuckoo/web/src/bower.json b/cuckoo/web/src/bower.json index 9ac82fd033..f6a082f6e0 100644 --- a/cuckoo/web/src/bower.json +++ b/cuckoo/web/src/bower.json @@ -25,7 +25,6 @@ "js-cookie": "^2.1.4", "datatables": "^1.10.13", "highlight": "^9.10.0", - "lightbox2": "lightbox#^2.9.0", "jquery-ui": "^1.12.1" } } diff --git a/cuckoo/web/src/scss/plugins/_jstree.scss b/cuckoo/web/src/scss/plugins/_jstree.scss index ead0ed3cf3..e8af89bcaa 100644 --- a/cuckoo/web/src/scss/plugins/_jstree.scss +++ b/cuckoo/web/src/scss/plugins/_jstree.scss @@ -15,7 +15,7 @@ .jstree-default .jstree-clicked, .jstree-default .jstree-wholerow-hovered { background: transparent !important; box-shadow: none; } .jstree-grid-header-regular { text-align: center !important; margin-bottom: 21px !important; background-color: #f9f9f9; } .jstree-grid-wrapper { padding-bottom: 20px !important; } -.jstree-grid-midwrapper { background: url("/static/img/theme_default/table_bg_22px.png"); background-position-y: 2px; } +.jstree-grid-midwrapper { background: url("/static/images/theme_default/table_bg_22px.png"); background-position-y: 2px; } .jstree-grid-cell { color: #929292; } .jstree-default.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox, .jstree-default .jstree-checked>.jstree-checkbox { background-position: -228px -4px; } .jstree-default .jstree-clicked.jstree-grid-col-0, .jstree-default .jstree-checked { color: #4c4c4c; } diff --git a/cuckoo/web/static/css/lightbox.css b/cuckoo/web/static/css/lightbox.css new file mode 100644 index 0000000000..e3125498d4 --- /dev/null +++ b/cuckoo/web/static/css/lightbox.css @@ -0,0 +1,205 @@ +/* Preload images */ +body:after { + content: url(../images/close.png) url(../images/loading.gif) url(../images/prev.png) url(../images/next.png); + display: none; +} + +.lightboxOverlay { + position: absolute; + top: 0; + left: 0; + z-index: 9999; + background-color: black; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); + opacity: 0.8; + display: none; +} + +.lightbox { + position: absolute; + left: 0; + width: 100%; + z-index: 10000; + text-align: center; + line-height: 0; + font-weight: normal; +} + +.lightbox .lb-image { + display: block; + height: auto; + max-width: inherit; +} + +.lightbox a img { + border: none; +} + +.lb-outerContainer { + position: relative; + background-color: white; + *zoom: 1; + width: 250px; + height: 250px; + margin: 0 auto; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + -ms-border-radius: 4px; + -o-border-radius: 4px; + border-radius: 4px; +} + +.lb-outerContainer:after { + content: ""; + display: table; + clear: both; +} + +.lb-container { + padding: 4px; +} + +.lb-loader { + position: absolute; + top: 43%; + left: 0; + height: 25%; + width: 100%; + text-align: center; + line-height: 0; +} + +.lb-cancel { + display: block; + width: 32px; + height: 32px; + margin: 0 auto; + background: url(../images/loading.gif) no-repeat; +} + +.lb-nav { + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + z-index: 10; +} + +.lb-container > .nav { + left: 0; +} + +.lb-nav a { + outline: none; + background-image: url('data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='); +} + +.lb-prev, .lb-next { + height: 100%; + cursor: pointer; + display: block; +} + +.lb-nav a.lb-prev { + width: 34%; + left: 0; + float: left; + background: url(../images/prev.png) left 48% no-repeat; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0); + opacity: 0; + -webkit-transition: opacity 0.6s; + -moz-transition: opacity 0.6s; + -o-transition: opacity 0.6s; + transition: opacity 0.6s; +} + +.lb-nav a.lb-prev:hover { + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); + opacity: 1; +} + +.lb-nav a.lb-next { + width: 64%; + right: 0; + float: right; + background: url(../images/next.png) right 48% no-repeat; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0); + opacity: 0; + -webkit-transition: opacity 0.6s; + -moz-transition: opacity 0.6s; + -o-transition: opacity 0.6s; + transition: opacity 0.6s; +} + +.lb-nav a.lb-next:hover { + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); + opacity: 1; +} + +.lb-dataContainer { + margin: 0 auto; + padding-top: 5px; + *zoom: 1; + width: 100%; + -moz-border-radius-bottomleft: 4px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomright: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; +} + +.lb-dataContainer:after { + content: ""; + display: table; + clear: both; +} + +.lb-data { + padding: 0 4px; + color: #ccc; +} + +.lb-data .lb-details { + width: 85%; + float: left; + text-align: left; + line-height: 1.1em; +} + +.lb-data .lb-caption { + font-size: 13px; + font-weight: bold; + line-height: 1em; +} + +.lb-data .lb-number { + display: block; + clear: left; + padding-bottom: 1em; + font-size: 12px; + color: #999999; +} + +.lb-data .lb-close { + display: block; + float: right; + width: 30px; + height: 30px; + background: url(../images/close.png) top right no-repeat; + text-align: right; + outline: none; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=70); + opacity: 0.7; + -webkit-transition: opacity 0.2s; + -moz-transition: opacity 0.2s; + -o-transition: opacity 0.2s; + transition: opacity 0.2s; +} + +.lb-data .lb-close:hover { + cursor: pointer; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); + opacity: 1; +} diff --git a/cuckoo/web/static/css/main.css b/cuckoo/web/static/css/main.css index 59023a34ad..6bb14afe0b 100644 --- a/cuckoo/web/static/css/main.css +++ b/cuckoo/web/static/css/main.css @@ -7986,7 +7986,7 @@ body.night .dashboard table.simple tr:nth-child(even) { } .jstree-grid-midwrapper { - background: url("/static/img/theme_default/table_bg_22px.png"); + background: url("/static/images/theme_default/table_bg_22px.png"); background-position-y: 2px; } diff --git a/cuckoo/web/static/css/vendor.css b/cuckoo/web/static/css/vendor.css index 228def7a43..57ddfb3e43 100644 --- a/cuckoo/web/static/css/vendor.css +++ b/cuckoo/web/static/css/vendor.css @@ -6896,42 +6896,6 @@ body.lb-disable-scrolling { overflow: hidden; } -.lightboxOverlay { - position: absolute; - top: 0; - left: 0; - z-index: 9999; - background-color: black; - filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); - opacity: 0.8; - display: none; -} - -.lightbox { - position: absolute; - left: 0; - width: 100%; - z-index: 10000; - text-align: center; - line-height: 0; - font-weight: normal; -} - -.lightbox .lb-image { - display: block; - height: auto; - max-width: inherit; - max-height: none; - border-radius: 3px; - - /* Image border */ - border: 4px solid white; -} - -.lightbox a img { - border: none; -} - .lb-outerContainer { position: relative; *zoom: 1; diff --git a/cuckoo/web/static/js/misc/lightbox.js b/cuckoo/web/static/js/misc/lightbox.js new file mode 100644 index 0000000000..b3dacb6d52 --- /dev/null +++ b/cuckoo/web/static/js/misc/lightbox.js @@ -0,0 +1,411 @@ +/** + * Lightbox v2.7.1 + * by Lokesh Dhakar - http://lokeshdhakar.com/projects/lightbox2/ + * + * @license http://creativecommons.org/licenses/by/2.5/ + * - Free for use in both personal and commercial projects + * - Attribution requires leaving author name, author link, and the license info intact + */ + +(function() { + // Use local alias + var $ = jQuery; + + var LightboxOptions = (function() { + function LightboxOptions() { + this.fadeDuration = 300; + this.fitImagesInViewport = true; + this.resizeDuration = 300; + this.positionFromTop = 50; + this.showImageNumberLabel = true; + this.alwaysShowNavOnTouchDevices = false; + this.wrapAround = false; + } + + // Change to localize to non-english language + LightboxOptions.prototype.albumLabel = function(curImageNum, albumSize) { + return "Image " + curImageNum + " of " + albumSize; + }; + + return LightboxOptions; + })(); + + + var Lightbox = (function() { + function Lightbox(options) { + this.options = options; + this.album = []; + this.currentImageIndex = void 0; + this.init(); + } + + Lightbox.prototype.init = function() { + this.enable(); + this.build(); + }; + + // Loop through anchors and areamaps looking for either data-lightbox attributes or rel attributes + // that contain 'lightbox'. When these are clicked, start lightbox. + Lightbox.prototype.enable = function() { + var self = this; + $('body').on('click', 'a[rel^=lightbox], area[rel^=lightbox], a[data-lightbox], area[data-lightbox]', function(event) { + self.start($(event.currentTarget)); + return false; + }); + }; + + // Build html for the lightbox and the overlay. + // Attach event handlers to the new DOM elements. click click click + Lightbox.prototype.build = function() { + var self = this; + $("
").appendTo($('body')); + + // Cache jQuery objects + this.$lightbox = $('#lightbox'); + this.$overlay = $('#lightboxOverlay'); + this.$outerContainer = this.$lightbox.find('.lb-outerContainer'); + this.$container = this.$lightbox.find('.lb-container'); + + // Store css values for future lookup + this.containerTopPadding = parseInt(this.$container.css('padding-top'), 10); + this.containerRightPadding = parseInt(this.$container.css('padding-right'), 10); + this.containerBottomPadding = parseInt(this.$container.css('padding-bottom'), 10); + this.containerLeftPadding = parseInt(this.$container.css('padding-left'), 10); + + // Attach event handlers to the newly minted DOM elements + this.$overlay.hide().on('click', function() { + self.end(); + return false; + }); + + this.$lightbox.hide().on('click', function(event) { + if ($(event.target).attr('id') === 'lightbox') { + self.end(); + } + return false; + }); + + this.$outerContainer.on('click', function(event) { + if ($(event.target).attr('id') === 'lightbox') { + self.end(); + } + return false; + }); + + this.$lightbox.find('.lb-prev').on('click', function() { + if (self.currentImageIndex === 0) { + self.changeImage(self.album.length - 1); + } else { + self.changeImage(self.currentImageIndex - 1); + } + return false; + }); + + this.$lightbox.find('.lb-next').on('click', function() { + if (self.currentImageIndex === self.album.length - 1) { + self.changeImage(0); + } else { + self.changeImage(self.currentImageIndex + 1); + } + return false; + }); + + this.$lightbox.find('.lb-loader, .lb-close').on('click', function() { + self.end(); + return false; + }); + }; + + // Show overlay and lightbox. If the image is part of a set, add siblings to album array. + Lightbox.prototype.start = function($link) { + var self = this; + var $window = $(window); + + $window.on('resize', $.proxy(this.sizeOverlay, this)); + + $('select, object, embed').css({ + visibility: "hidden" + }); + + this.sizeOverlay(); + + this.album = []; + var imageNumber = 0; + + function addToAlbum($link) { + self.album.push({ + link: $link.attr('href'), + title: $link.attr('data-title') || $link.attr('title') + }); + } + + // Support both data-lightbox attribute and rel attribute implementations + var dataLightboxValue = $link.attr('data-lightbox'); + var $links; + + if (dataLightboxValue) { + $links = $($link.prop("tagName") + '[data-lightbox="' + dataLightboxValue + '"]'); + for (var i = 0; i < $links.length; i = ++i) { + addToAlbum($($links[i])); + if ($links[i] === $link[0]) { + imageNumber = i; + } + } + } else { + if ($link.attr('rel') === 'lightbox') { + // If image is not part of a set + addToAlbum($link); + } else { + // If image is part of a set + $links = $($link.prop("tagName") + '[rel="' + $link.attr('rel') + '"]'); + for (var j = 0; j < $links.length; j = ++j) { + addToAlbum($($links[j])); + if ($links[j] === $link[0]) { + imageNumber = j; + } + } + } + } + + // Position Lightbox + var top = $window.scrollTop() + this.options.positionFromTop; + var left = $window.scrollLeft(); + this.$lightbox.css({ + top: top + 'px', + left: left + 'px' + }).fadeIn(this.options.fadeDuration); + + this.changeImage(imageNumber); + }; + + // Hide most UI elements in preparation for the animated resizing of the lightbox. + Lightbox.prototype.changeImage = function(imageNumber) { + var self = this; + + this.disableKeyboardNav(); + var $image = this.$lightbox.find('.lb-image'); + + this.$overlay.fadeIn(this.options.fadeDuration); + + $('.lb-loader').fadeIn('slow'); + this.$lightbox.find('.lb-image, .lb-nav, .lb-prev, .lb-next, .lb-dataContainer, .lb-numbers, .lb-caption').hide(); + + this.$outerContainer.addClass('animating'); + + // When image to show is preloaded, we send the width and height to sizeContainer() + var preloader = new Image(); + preloader.onload = function() { + var $preloader, imageHeight, imageWidth, maxImageHeight, maxImageWidth, windowHeight, windowWidth; + $image.attr('src', self.album[imageNumber].link); + + $preloader = $(preloader); + + $image.width(preloader.width); + $image.height(preloader.height); + + if (self.options.fitImagesInViewport) { + // Fit image inside the viewport. + // Take into account the border around the image and an additional 10px gutter on each side. + + windowWidth = $(window).width(); + windowHeight = $(window).height(); + maxImageWidth = windowWidth - self.containerLeftPadding - self.containerRightPadding - 20; + maxImageHeight = windowHeight - self.containerTopPadding - self.containerBottomPadding - 120; + + // Is there a fitting issue? + if ((preloader.width > maxImageWidth) || (preloader.height > maxImageHeight)) { + if ((preloader.width / maxImageWidth) > (preloader.height / maxImageHeight)) { + imageWidth = maxImageWidth; + imageHeight = parseInt(preloader.height / (preloader.width / imageWidth), 10); + $image.width(imageWidth); + $image.height(imageHeight); + } else { + imageHeight = maxImageHeight; + imageWidth = parseInt(preloader.width / (preloader.height / imageHeight), 10); + $image.width(imageWidth); + $image.height(imageHeight); + } + } + } + self.sizeContainer($image.width(), $image.height()); + }; + + preloader.src = this.album[imageNumber].link; + this.currentImageIndex = imageNumber; + }; + + // Stretch overlay to fit the viewport + Lightbox.prototype.sizeOverlay = function() { + this.$overlay + .width($(window).width()) + .height($(document).height()); + }; + + // Animate the size of the lightbox to fit the image we are showing + Lightbox.prototype.sizeContainer = function(imageWidth, imageHeight) { + var self = this; + + var oldWidth = this.$outerContainer.outerWidth(); + var oldHeight = this.$outerContainer.outerHeight(); + var newWidth = imageWidth + this.containerLeftPadding + this.containerRightPadding; + var newHeight = imageHeight + this.containerTopPadding + this.containerBottomPadding; + + function postResize() { + self.$lightbox.find('.lb-dataContainer').width(newWidth); + self.$lightbox.find('.lb-prevLink').height(newHeight); + self.$lightbox.find('.lb-nextLink').height(newHeight); + self.showImage(); + } + + if (oldWidth !== newWidth || oldHeight !== newHeight) { + this.$outerContainer.animate({ + width: newWidth, + height: newHeight + }, this.options.resizeDuration, 'swing', function() { + postResize(); + }); + } else { + postResize(); + } + }; + + // Display the image and it's details and begin preload neighboring images. + Lightbox.prototype.showImage = function() { + this.$lightbox.find('.lb-loader').hide(); + this.$lightbox.find('.lb-image').fadeIn('slow'); + + this.updateNav(); + this.updateDetails(); + this.preloadNeighboringImages(); + this.enableKeyboardNav(); + }; + + // Display previous and next navigation if appropriate. + Lightbox.prototype.updateNav = function() { + // Check to see if the browser supports touch events. If so, we take the conservative approach + // and assume that mouse hover events are not supported and always show prev/next navigation + // arrows in image sets. + var alwaysShowNav = false; + try { + document.createEvent("TouchEvent"); + alwaysShowNav = (this.options.alwaysShowNavOnTouchDevices)? true: false; + } catch (e) {} + + this.$lightbox.find('.lb-nav').show(); + + if (this.album.length > 1) { + if (this.options.wrapAround) { + if (alwaysShowNav) { + this.$lightbox.find('.lb-prev, .lb-next').css('opacity', '1'); + } + this.$lightbox.find('.lb-prev, .lb-next').show(); + } else { + if (this.currentImageIndex > 0) { + this.$lightbox.find('.lb-prev').show(); + if (alwaysShowNav) { + this.$lightbox.find('.lb-prev').css('opacity', '1'); + } + } + if (this.currentImageIndex < this.album.length - 1) { + this.$lightbox.find('.lb-next').show(); + if (alwaysShowNav) { + this.$lightbox.find('.lb-next').css('opacity', '1'); + } + } + } + } + }; + + // Display caption, image number, and closing button. + Lightbox.prototype.updateDetails = function() { + var self = this; + + // Enable anchor clicks in the injected caption html. + // Thanks Nate Wright for the fix. @https://github.com/NateWr + if (typeof this.album[this.currentImageIndex].title !== 'undefined' && this.album[this.currentImageIndex].title !== "") { + this.$lightbox.find('.lb-caption') + .html(this.album[this.currentImageIndex].title) + .fadeIn('fast') + .find('a').on('click', function(event){ + location.href = $(this).attr('href'); + }); + } + + if (this.album.length > 1 && this.options.showImageNumberLabel) { + this.$lightbox.find('.lb-number').text(this.options.albumLabel(this.currentImageIndex + 1, this.album.length)).fadeIn('fast'); + } else { + this.$lightbox.find('.lb-number').hide(); + } + + this.$outerContainer.removeClass('animating'); + + this.$lightbox.find('.lb-dataContainer').fadeIn(this.options.resizeDuration, function() { + return self.sizeOverlay(); + }); + }; + + // Preload previous and next images in set. + Lightbox.prototype.preloadNeighboringImages = function() { + if (this.album.length > this.currentImageIndex + 1) { + var preloadNext = new Image(); + preloadNext.src = this.album[this.currentImageIndex + 1].link; + } + if (this.currentImageIndex > 0) { + var preloadPrev = new Image(); + preloadPrev.src = this.album[this.currentImageIndex - 1].link; + } + }; + + Lightbox.prototype.enableKeyboardNav = function() { + $(document).on('keyup.keyboard', $.proxy(this.keyboardAction, this)); + }; + + Lightbox.prototype.disableKeyboardNav = function() { + $(document).off('.keyboard'); + }; + + Lightbox.prototype.keyboardAction = function(event) { + var KEYCODE_ESC = 27; + var KEYCODE_LEFTARROW = 37; + var KEYCODE_RIGHTARROW = 39; + + var keycode = event.keyCode; + var key = String.fromCharCode(keycode).toLowerCase(); + if (keycode === KEYCODE_ESC || key.match(/x|o|c/)) { + this.end(); + } else if (key === 'p' || keycode === KEYCODE_LEFTARROW) { + if (this.currentImageIndex !== 0) { + this.changeImage(this.currentImageIndex - 1); + } else if (this.options.wrapAround && this.album.length > 1) { + this.changeImage(this.album.length - 1); + } + } else if (key === 'n' || keycode === KEYCODE_RIGHTARROW) { + if (this.currentImageIndex !== this.album.length - 1) { + this.changeImage(this.currentImageIndex + 1); + } else if (this.options.wrapAround && this.album.length > 1) { + this.changeImage(0); + } + } + }; + + // Closing time. :-( + Lightbox.prototype.end = function() { + this.disableKeyboardNav(); + $(window).off("resize", this.sizeOverlay); + this.$lightbox.fadeOut(this.options.fadeDuration); + this.$overlay.fadeOut(this.options.fadeDuration); + $('select, object, embed').css({ + visibility: "visible" + }); + }; + + return Lightbox; + + })(); + + $(function() { + var options = new LightboxOptions(); + var lightbox = new Lightbox(options); + }); + +}).call(this); diff --git a/cuckoo/web/templates/footer.html b/cuckoo/web/templates/footer.html index a3eb35c03e..ea7e0317b9 100644 --- a/cuckoo/web/templates/footer.html +++ b/cuckoo/web/templates/footer.html @@ -296,5 +296,6 @@ + diff --git a/cuckoo/web/templates/header.html b/cuckoo/web/templates/header.html index eff2d22d90..c52006f237 100644 --- a/cuckoo/web/templates/header.html +++ b/cuckoo/web/templates/header.html @@ -12,6 +12,7 @@ + {% if report.analysis.info.id %}