From fc577de07728b7dc02c15e91f518eb4ba4196ed2 Mon Sep 17 00:00:00 2001 From: TomBaxter Date: Fri, 16 Jun 2017 09:36:27 -0400 Subject: [PATCH 1/5] [#SVCS-86] Add papaya renderer for NifTI and DICOM files. Add customization to papaya library to disallow opening of new files from user desktop. Consulted with Product Team. They determined that it would be confusing and possibly dangerous to allow opening of files from user desktop, when they might confuse it with the WaterButler repository. Used a custom built papaya.js built on https://github.com/TomBaxter/Papaya/tree/feature/noNewFiles I have sent them a PR, hopefully they bite. https://github.com/rii-mango/Papaya/pull/101 --- mfr/extensions/papaya/__init__.py | 1 + mfr/extensions/papaya/render.py | 48 + mfr/extensions/papaya/settings.py | 8 + .../papaya/static/README-papaya.txt | 7 + mfr/extensions/papaya/static/data/.gitignore | 4 + mfr/extensions/papaya/static/papaya.css | 1 + mfr/extensions/papaya/static/papaya.js | 2105 +++++++++++++++++ mfr/extensions/papaya/templates/viewer.mako | 21 + mfr/extensions/settings.py | 5 + mfr/server/handlers/render.py | 10 +- setup.py | 5 + tests/extensions/papaya/__init__.py | 0 .../507643e2-c0fb-45e4-805e-96231c8251de | Bin 0 -> 971645 bytes tests/extensions/papaya/test_renderer.py | 45 + 14 files changed, 2259 insertions(+), 1 deletion(-) create mode 100644 mfr/extensions/papaya/__init__.py create mode 100644 mfr/extensions/papaya/render.py create mode 100644 mfr/extensions/papaya/settings.py create mode 100644 mfr/extensions/papaya/static/README-papaya.txt create mode 100644 mfr/extensions/papaya/static/data/.gitignore create mode 100644 mfr/extensions/papaya/static/papaya.css create mode 100644 mfr/extensions/papaya/static/papaya.js create mode 100644 mfr/extensions/papaya/templates/viewer.mako create mode 100644 mfr/extensions/settings.py create mode 100644 tests/extensions/papaya/__init__.py create mode 100644 tests/extensions/papaya/files/507643e2-c0fb-45e4-805e-96231c8251de create mode 100644 tests/extensions/papaya/test_renderer.py diff --git a/mfr/extensions/papaya/__init__.py b/mfr/extensions/papaya/__init__.py new file mode 100644 index 000000000..4b3a4eba1 --- /dev/null +++ b/mfr/extensions/papaya/__init__.py @@ -0,0 +1 @@ +from .render import PapayaRenderer # noqa diff --git a/mfr/extensions/papaya/render.py b/mfr/extensions/papaya/render.py new file mode 100644 index 000000000..63e49ae3d --- /dev/null +++ b/mfr/extensions/papaya/render.py @@ -0,0 +1,48 @@ +import os +import time +import shutil + +from mako.lookup import TemplateLookup + +from mfr.core import extension +from mfr.extensions import settings as ext_settings +from mfr.extensions.papaya import settings + + +class PapayaRenderer(extension.BaseRenderer): + + data_dir = settings.DATA_DIR + data_old = settings.DATA_OLD + comp_ext = ext_settings.COMPRESSED_EXT + + TEMPLATE = TemplateLookup( + directories=[ + os.path.join(os.path.dirname(__file__), 'templates') + ]).get_template('viewer.mako') + + def render(self): + self.remove_old_files() + file_name = os.path.basename(self.file_path) + if self.metadata.ext in self.comp_ext.keys(): + second_ext = '.{}'.format(self.metadata.name.split('.')[-1]) + if second_ext in self.comp_ext[self.metadata.ext]: + file_name = file_name + second_ext + file_name = file_name + self.metadata.ext + shutil.copyfile(self.file_path, self.data_dir + file_name) + return self.TEMPLATE.render(base=self.assets_url, file_name=file_name) + + def remove_old_files(self): + + for data_file in os.listdir(self.data_dir): + if data_file == '.gitignore': + continue + if (time.time() - os.path.getctime(self.data_dir + data_file)) >= self.data_old: + os.unlink(self.data_dir + data_file) + + @property + def file_required(self): + return True + + @property + def cache_result(self): + return True diff --git a/mfr/extensions/papaya/settings.py b/mfr/extensions/papaya/settings.py new file mode 100644 index 000000000..d1d9c5f35 --- /dev/null +++ b/mfr/extensions/papaya/settings.py @@ -0,0 +1,8 @@ +from mfr import settings + +config = settings.child('PAPAYA_EXTENSION_CONFIG') + +# Directory to temporarily store papaya image files +DATA_DIR = 'mfr/extensions/papaya/static/data/' +# Files older then this many seconds will be deleted from DATA_DIR at the beggining of each render. +DATA_OLD = 300 diff --git a/mfr/extensions/papaya/static/README-papaya.txt b/mfr/extensions/papaya/static/README-papaya.txt new file mode 100644 index 000000000..83045ba29 --- /dev/null +++ b/mfr/extensions/papaya/static/README-papaya.txt @@ -0,0 +1,7 @@ +Currently using a custom built papaya.js with option to remove the ability to open new files from the users desktop. + +https://github.com/TomBaxter/Papaya/tree/feature/noNewFiles + +I have sent them a PR, hopefully they bite. + +https://github.com/rii-mango/Papaya/pull/101 diff --git a/mfr/extensions/papaya/static/data/.gitignore b/mfr/extensions/papaya/static/data/.gitignore new file mode 100644 index 000000000..5e7d2734c --- /dev/null +++ b/mfr/extensions/papaya/static/data/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore diff --git a/mfr/extensions/papaya/static/papaya.css b/mfr/extensions/papaya/static/papaya.css new file mode 100644 index 000000000..c9e3dd8ab --- /dev/null +++ b/mfr/extensions/papaya/static/papaya.css @@ -0,0 +1 @@ +.papaya{width:90%;height:90%;margin:25px auto;background-color:black;font-family:sans-serif}.papaya:before{position:relative;content:"Papaya requires JavaScript...";display:block;top:45%;color:red;margin:0 auto;font-size:18px;font-family:sans-serif}.papaya-fullscreen{height:100%}.papaya-toolbar{text-align:left;box-sizing:content-box;position:relative}.papaya-toolbar ul{margin:0;list-style:none}.papaya-toolbar input[type=file]{text-align:right;display:none}.papaya-kiosk-controls{position:relative;margin:5px auto;list-style:none;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.papaya-kiosk-controls ul{list-style:none}.papaya-kiosk-controls button{-webkit-appearance:none;border-radius:0;-webkit-border-radius:0;font-size:14px;height:25px;background-color:lightgray}.papaya-control-increment{-webkit-appearance:none;border-radius:0;-webkit-border-radius:0;font-size:14px;height:25px;width:25px;text-align:center;vertical-align:middle;padding:0;margin-left:auto;margin-right:auto;line-height:16px;box-sizing:border-box;font-family:"Courier New",Courier,monospace}.papaya-main-increment{-webkit-appearance:none;border-radius:0;-webkit-border-radius:0;font-size:14px;height:25px;width:25px;text-align:center;font-family:"Courier New",Courier,monospace;background-color:lightgray;vertical-align:middle;padding:0;margin-left:auto;margin-right:auto;box-sizing:border-box;outline:0}.papaya-main-decrement{-webkit-appearance:none;border-radius:0;-webkit-border-radius:0;font-size:14px;height:25px;width:25px;text-align:center;font-family:"Courier New",Courier,monospace;background-color:lightgray;vertical-align:middle;padding:0;margin-left:auto;margin-right:auto;box-sizing:border-box;outline:0}.papaya-main-swap{-webkit-appearance:none;border-radius:0;-webkit-border-radius:0;font-size:14px;height:25px;background-color:lightgray;outline:0}.papaya-main-goto-center{-webkit-appearance:none;border-radius:0;-webkit-border-radius:0;font-size:14px;height:25px;background-color:lightgray;outline:0}.papaya-main-goto-origin{-webkit-appearance:none;border-radius:0;-webkit-border-radius:0;font-size:14px;height:25px;background-color:lightgray;outline:0}.papaya-slider-slice{padding:0 5px;display:inline}.papaya-slider-slice span{font-size:14px;font-family:sans-serif;vertical-align:middle}.papaya-slider-slice button{-webkit-appearance:none;border-radius:0;-webkit-border-radius:0;vertical-align:middle;font-size:14px;height:25px;background-color:lightgray}.papaya-controlbar-label{color:#000}.papaya-menu{width:220px;background:#222;z-index:100;position:absolute;border:solid 2px darkgray;padding:4px;margin:0}.papaya-menu li{font-size:12px;font-family:sans-serif;padding:4px 2px;color:#b5cbd3;cursor:pointer;list-style-type:none}.papaya-menu-label{font-size:14px;font-family:sans-serif;font-weight:bold;padding:2px 8px;cursor:pointer;vertical-align:text-bottom}.papaya-menu-titlebar{font-size:16px;font-family:sans-serif;padding:3px 8px 0 8px;cursor:default;vertical-align:text-bottom;color:white}.papaya-menu-icon{margin-left:5px}.papaya-menu-icon img{box-sizing:content-box}.papaya-menu-hovering{background-color:#444}.papaya-menu-spacer{height:8px}.papaya-menu-unselectable{-moz-user-select:-moz-none;-khtml-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;-webkit-user-drag:none;user-drag:none}.papaya-menu-button-hovering{background-color:#DDD}.papaya-menu-filechooser{cursor:pointer;width:200px;display:inline-block;font-weight:normal}.papaya-menu-input{width:38px;margin-right:5px;color:black}li .papaya-menu-slider{vertical-align:middle;text-align:center;display:inline;width:120px;padding:0;margin:0}.papaya-dialog{min-width:400px;max-width:500px;height:500px;background:#222;position:absolute;z-index:100;border:solid 2px darkgray;padding:6px;font-size:14px;font-family:sans-serif;color:#b5cbd3;box-sizing:content-box;line-height:1.45}.papaya-dialog-content{margin:20px;height:415px;color:#dedede;overflow:auto;-ms-overflow-style:-ms-autohiding-scrollbar}.papaya-dialog-content-nowrap{white-space:nowrap}.papaya-dialog-content table{margin:0 auto}.papaya-dialog-content-label{text-align:right;padding:5px;color:#b5cbd3}.papaya-dialog-content-control{text-align:left;padding:5px}.papaya-dialog-content-help{text-align:right;padding:5px;color:lightgray;font-size:12px}.papaya-dialog-title{color:#b5cbd3;font-weight:bold;font-size:16px}.papaya-dialog-button{text-align:right;box-sizing:content-box;height:22px}.papaya-dialog-button button{box-sizing:content-box;color:black;font-size:11px}.papaya-dialog-background{position:fixed;top:0;left:0;background-color:#fff;width:100%;height:100%;opacity:.5}.papaya-dialog-stopscroll{height:100%;overflow:hidden}.checkForJS{width:90%;height:90%;margin:25px auto;background-color:black}.checkForJS:before{position:relative;content:"Papaya requires JavaScript...";display:block;top:45%;color:red;margin:0 auto;font-size:18px;font-family:sans-serif;text-align:center}.papaya-utils-unsupported{width:90%;height:90%;margin:25px auto;background-color:black}.papaya-utils-unsupported-message{position:relative;display:block;top:45%;color:red;margin:0 auto;font-size:18px;font-family:sans-serif;text-align:center}.papaya-viewer{line-height:1;font-family:sans-serif}.papaya-viewer div,.papaya-viewer canvas{margin:0;padding:0;border:0;font:inherit;font-size:100%;vertical-align:baseline;font-family:sans-serif}.papaya-viewer canvas{cursor:crosshair} \ No newline at end of file diff --git a/mfr/extensions/papaya/static/papaya.js b/mfr/extensions/papaya/static/papaya.js new file mode 100644 index 000000000..945b5f9d3 --- /dev/null +++ b/mfr/extensions/papaya/static/papaya.js @@ -0,0 +1,2105 @@ +var PAPAYA_BUILD_NUM="1430",papayaLoadableImages=[]; +(function(c,a){function d(c){var a=c.length,b=r.type(c);return r.isWindow(c)?!1:1===c.nodeType&&a?!0:"array"===b||"function"!==b&&(0===a||"number"===typeof a&&0a;a+=2)"margin"===b&&(g+=r.css(c,b+ya[a],!0,d)),e?("content"===b&&(g-=r.css(c,"padding"+ya[a],!0,d)),"margin"!==b&&(g-=r.css(c,"border"+ +ya[a]+"Width",!0,d))):(g+=r.css(c,"padding"+ya[a],!0,d),"padding"!==b&&(g+=r.css(c,"border"+ya[a]+"Width",!0,d)));return g}function D(c,a,b){var e=!0,d="width"===a?c.offsetWidth:c.offsetHeight,g=ja(c),l=r.support.boxSizing&&"border-box"===r.css(c,"boxSizing",!1,g);if(0>=d||null==d){d=Oa(c,a,g);if(0>d||null==d)d=c.style[a];if(wb.test(d))return d;e=l&&(r.support.boxSizingReliable||d===c.style[a]);d=parseFloat(d)||0}return d+y(c,a,b||(l?"border":"content"),e,g)+"px"}function u(c){var a=S,b=xb[c];b|| +(b=n(c,a),"none"!==b&&b||(wa=(wa||r(""),setTimeout(function(){try{b.location.href,e=!0}catch(a){console.log(a)}e?b.setTimeout("window.close()",100):b.close();d(e)},100);else if("Firefox"===papaya.utilities.PlatformUtils.browser){try{f=$("