From 8095de8759259dcc32409191259caa997026585a Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Tue, 12 Jan 2016 19:59:16 -0800 Subject: [PATCH] merge ronalds changes from upstream + some vm and dashboard fixes --- logging.htm | 10 +- .../DockerContainers.page | 20 +- plugins/dynamix.plugin.manager/Plugins.page | 21 +- .../icons/pluginfileinstallerrors.png | Bin 0 -> 878 bytes .../include/ShowPlugins.php | 18 +- plugins/dynamix.plugin.manager/scripts/plugin | 2 +- .../scripts/plugincheck | 19 +- plugins/dynamix.vm.manager/VMMachines.page | 25 +- .../dynamix.vm.manager/include/inflator.js | 27 +- plugins/dynamix.vm.manager/include/jsunzip.js | 676 ------------------ plugins/dynamix.vm.manager/include/rfb.js | 30 +- plugins/dynamix.vm.manager/include/ui.js | 20 +- plugins/dynamix.vm.manager/include/websock.js | 64 +- plugins/dynamix.vm.manager/include/webutil.js | 47 ++ plugins/dynamix.vm.manager/vnc.html | 3 + plugins/dynamix/ArrayDevices.page | 6 +- plugins/dynamix/ArrayOperation.page | 75 +- plugins/dynamix/BootDevice.page | 4 +- plugins/dynamix/CacheDevices.page | 4 +- plugins/dynamix/DashStats.page | 149 ++-- plugins/dynamix/DashboardApps.page | 10 +- plugins/dynamix/DeviceAttributes.page | 5 +- plugins/dynamix/DeviceCapabilities.page | 5 +- plugins/dynamix/DeviceIdentify.page | 5 +- plugins/dynamix/DeviceInfo.page | 288 ++++---- plugins/dynamix/DiskList.page | 84 +-- plugins/dynamix/DiskSettings.page | 128 +++- plugins/dynamix/DisplaySettings.page | 125 +--- plugins/dynamix/FTP.page | 18 +- plugins/dynamix/HelpButton.page | 7 +- plugins/dynamix/MoverSettings.page | 4 +- plugins/dynamix/New.page | 1 + plugins/dynamix/Notifications.page | 64 -- plugins/dynamix/NotificationsArchive.page | 54 +- plugins/dynamix/OpenDevices.page | 4 +- plugins/dynamix/PageMap.page | 16 +- plugins/dynamix/Processes.page | 16 +- plugins/dynamix/SMBExtras.page | 38 + plugins/dynamix/Selftest.page | 220 ++++++ plugins/dynamix/ShareEdit.page | 19 +- plugins/dynamix/ShareList.page | 87 +-- plugins/dynamix/ShareSettings.page | 16 +- plugins/dynamix/SmtpSettings.page | 6 +- plugins/dynamix/Syslog.page | 51 +- plugins/dynamix/UserList.page | 3 + plugins/dynamix/Users.page | 6 +- plugins/dynamix/Vars.page | 14 +- plugins/dynamix/default.cfg | 4 +- plugins/dynamix/dynamix.plg | 19 +- plugins/dynamix/icons/smb.png | Bin 1042 -> 948 bytes plugins/dynamix/icons/smbsecuritysettings.png | Bin 1042 -> 948 bytes plugins/dynamix/icons/smbsettings.png | Bin 1042 -> 948 bytes plugins/dynamix/images/alert.png | Bin 0 -> 722 bytes plugins/dynamix/images/help-off.png | Bin 0 -> 1859 bytes plugins/dynamix/images/help-on.png | Bin 0 -> 1896 bytes plugins/dynamix/images/users.png | Bin 0 -> 4123 bytes plugins/dynamix/images/windows-logo.png | Bin 4953 -> 5053 bytes plugins/dynamix/include/Acknowledge.php | 27 + plugins/dynamix/include/ColorCoding.php | 35 + plugins/dynamix/include/CustomMerge.php | 18 + plugins/dynamix/include/DashUpdate.php | 125 ++-- plugins/dynamix/include/DefaultPageLayout.php | 5 +- plugins/dynamix/include/DeleteLogFile.php | 6 +- plugins/dynamix/include/DeviceList.php | 363 ++++------ plugins/dynamix/include/DiskList.php | 114 +++ plugins/dynamix/include/Dispatcher.php | 27 + plugins/dynamix/include/Helpers.php | 51 +- .../dynamix/include/NotificationsArchive.php | 27 +- plugins/dynamix/include/PageBuilder.php | 20 +- plugins/dynamix/include/ParityHistory.php | 51 ++ plugins/dynamix/include/Preselect.php | 23 + plugins/dynamix/include/ShareList.php | 114 +++ plugins/dynamix/include/SmartInfo.php | 129 ++-- plugins/dynamix/include/Watchdog.php | 12 +- plugins/dynamix/include/update.parity.php | 2 +- plugins/dynamix/include/update.smart.php | 26 + plugins/dynamix/scripts/diagnostics | 2 +- plugins/dynamix/scripts/disk_log | 30 + plugins/dynamix/scripts/disk_size | 16 +- plugins/dynamix/scripts/ftpusers | 14 +- plugins/dynamix/scripts/hd_parm | 5 + plugins/dynamix/scripts/monitor | 332 ++++++--- plugins/dynamix/scripts/notify | 8 +- plugins/dynamix/scripts/share_size | 17 +- plugins/dynamix/scripts/spindowndelay | 41 ++ plugins/dynamix/scripts/statuscheck | 89 +-- plugins/dynamix/scripts/tail_log | 30 +- plugins/dynamix/styles/default-black.css | 14 +- plugins/dynamix/styles/default-white.css | 14 +- plugins/dynamix/styles/dynamix-black.css | 3 +- plugins/dynamix/styles/dynamix-white.css | 3 +- plugins/dynamix/template.php | 11 +- 92 files changed, 2466 insertions(+), 1875 deletions(-) create mode 100644 plugins/dynamix.plugin.manager/icons/pluginfileinstallerrors.png delete mode 100644 plugins/dynamix.vm.manager/include/jsunzip.js create mode 100644 plugins/dynamix/New.page create mode 100644 plugins/dynamix/SMBExtras.page create mode 100644 plugins/dynamix/Selftest.page create mode 100644 plugins/dynamix/images/alert.png create mode 100644 plugins/dynamix/images/help-off.png create mode 100644 plugins/dynamix/images/help-on.png create mode 100644 plugins/dynamix/images/users.png create mode 100644 plugins/dynamix/include/Acknowledge.php create mode 100644 plugins/dynamix/include/ColorCoding.php create mode 100644 plugins/dynamix/include/CustomMerge.php create mode 100644 plugins/dynamix/include/DiskList.php create mode 100644 plugins/dynamix/include/Dispatcher.php create mode 100644 plugins/dynamix/include/ParityHistory.php create mode 100644 plugins/dynamix/include/Preselect.php create mode 100644 plugins/dynamix/include/ShareList.php create mode 100644 plugins/dynamix/include/update.smart.php create mode 100755 plugins/dynamix/scripts/disk_log create mode 100755 plugins/dynamix/scripts/hd_parm create mode 100755 plugins/dynamix/scripts/spindowndelay diff --git a/logging.htm b/logging.htm index 5f86c9444..296470f84 100644 --- a/logging.htm +++ b/logging.htm @@ -27,7 +27,13 @@ src:url('/webGui/styles/bitstream.eot');src:url('/webGui/styles/bitstream.eot?#i button[type=button],a.button{font-family:arimo;font-size:11px;position:relative;display:inline-block;padding:5px 10px;border:1px solid #E8E8E8;border-radius:5px;margin:7px 14px 0 0;text-decoration:none;white-space:nowrap;cursor:pointer;outline:none;color:#303030;background:-webkit-radial-gradient(#F0F0F0,#C8C8C8);background:linear-gradient(#F0F0F0,#C8C8C8);} button:hover[type=button],a.button:hover{border-color:#6AB034;text-shadow:-1px -1px 0 rgba(0,0,0,0.3);color:#FFFFFF;background:-webkit-radial-gradient(#5E9E2E,#8FD956);background:linear-gradient(#5E9E2E,#8FD956);} button:active[type=button]{border-color:#6AB034;box-shadow:inset 0 0 8px 4px #548C29,0 1px 0 0 #E0E0E0;} - +p.centered{text-align:center;} +span.error{color:#D8000C;background-color:#FFBABA;display:block;width:100%;} +span.warn{color:#9F6000;background-color:#FEEFB3;display:block;width:100%;} +span.system{color:#00529B;background-color:#BDE5F8;display:block;width:100%;} +span.array{color:#4F8A10;background-color:#DFF2BF;display:block;width:100%;} +span.login{color:#D63301;background-color:#FFCCBA;display:block;width:100%;} +span.label{padding:4px 8px;margin-right:10px;border-radius:4px;display:inline;width:auto;} diff --git a/plugins/dynamix.docker.manager/DockerContainers.page b/plugins/dynamix.docker.manager/DockerContainers.page index 00eec6655..07498efbe 100644 --- a/plugins/dynamix.docker.manager/DockerContainers.page +++ b/plugins/dynamix.docker.manager/DockerContainers.page @@ -65,7 +65,7 @@ img.stopped{opacity:0.3;} Log - + getDockerContainers(); if ( ! $all_containers) { @@ -212,6 +212,19 @@ img.stopped{opacity:0.3;} - diff --git a/plugins/dynamix.vm.manager/include/inflator.js b/plugins/dynamix.vm.manager/include/inflator.js index 3a708dd2f..4cffd49d8 100644 --- a/plugins/dynamix.vm.manager/include/inflator.js +++ b/plugins/dynamix.vm.manager/include/inflator.js @@ -234,7 +234,8 @@ module.exports = function inflate_fast(strm, start) { var wsize; /* window size or zero if not using window */ var whave; /* valid bytes in the window */ var wnext; /* window write index */ - var window; /* allocated sliding window, if wsize != 0 */ + // Use `s_window` instead `window`, avoid conflict with instrumentation tools + var s_window; /* allocated sliding window, if wsize != 0 */ var hold; /* local strm.hold */ var bits; /* local strm.bits */ var lcode; /* local strm.lencode */ @@ -268,7 +269,7 @@ module.exports = function inflate_fast(strm, start) { wsize = state.wsize; whave = state.whave; wnext = state.wnext; - window = state.window; + s_window = state.window; hold = state.hold; bits = state.bits; lcode = state.lencode; @@ -386,13 +387,13 @@ module.exports = function inflate_fast(strm, start) { //#endif } from = 0; // window index - from_source = window; + from_source = s_window; if (wnext === 0) { /* very common case */ from += wsize - op; if (op < len) { /* some from window */ len -= op; do { - output[_out++] = window[from++]; + output[_out++] = s_window[from++]; } while (--op); from = _out - dist; /* rest from output */ from_source = output; @@ -404,14 +405,14 @@ module.exports = function inflate_fast(strm, start) { if (op < len) { /* some from end of window */ len -= op; do { - output[_out++] = window[from++]; + output[_out++] = s_window[from++]; } while (--op); from = 0; if (wnext < len) { /* some from start of window */ op = wnext; len -= op; do { - output[_out++] = window[from++]; + output[_out++] = s_window[from++]; } while (--op); from = _out - dist; /* rest from output */ from_source = output; @@ -423,7 +424,7 @@ module.exports = function inflate_fast(strm, start) { if (op < len) { /* some from window */ len -= op; do { - output[_out++] = window[from++]; + output[_out++] = s_window[from++]; } while (--op); from = _out - dist; /* rest from output */ from_source = output; @@ -2377,7 +2378,7 @@ var ZStream = require('./lib/zlib/zstream.js'); var Inflate = function () { this.strm = new ZStream(); - this.chunkSize = 1024 * 10 * 10 * 10; + this.chunkSize = 1024 * 10 * 10; this.strm.output = new Uint8Array(this.chunkSize); this.windowBits = 5; @@ -2385,12 +2386,20 @@ var Inflate = function () { }; Inflate.prototype = { - inflate: function (data, flush) { + inflate: function (data, flush, expected) { this.strm.input = data; this.strm.avail_in = this.strm.input.length; this.strm.next_in = 0; this.strm.next_out = 0; + // resize our output buffer if it's too small + // (we could just use multiple chunks, but that would cause an extra + // allocation each time to flatten the chunks) + if (expected > this.chunkSize) { + this.chunkSize = expected; + this.strm.output = new Uint8Array(this.chunkSize); + } + this.strm.avail_out = this.chunkSize; zlib.inflate(this.strm, flush); diff --git a/plugins/dynamix.vm.manager/include/jsunzip.js b/plugins/dynamix.vm.manager/include/jsunzip.js deleted file mode 100644 index 8968f866a..000000000 --- a/plugins/dynamix.vm.manager/include/jsunzip.js +++ /dev/null @@ -1,676 +0,0 @@ -/* - * JSUnzip - * - * Copyright (c) 2011 by Erik Moller - * All Rights Reserved - * - * This software is provided 'as-is', without any express - * or implied warranty. In no event will the authors be - * held liable for any damages arising from the use of - * this software. - * - * Permission is granted to anyone to use this software - * for any purpose, including commercial applications, - * and to alter it and redistribute it freely, subject to - * the following restrictions: - * - * 1. The origin of this software must not be - * misrepresented; you must not claim that you - * wrote the original software. If you use this - * software in a product, an acknowledgment in - * the product documentation would be appreciated - * but is not required. - * - * 2. Altered source versions must be plainly marked - * as such, and must not be misrepresented as - * being the original software. - * - * 3. This notice may not be removed or altered from - * any source distribution. - */ - -var tinf; - -function JSUnzip() { - - this.getInt = function(offset, size) { - switch (size) { - case 4: - return (this.data.charCodeAt(offset + 3) & 0xff) << 24 | - (this.data.charCodeAt(offset + 2) & 0xff) << 16 | - (this.data.charCodeAt(offset + 1) & 0xff) << 8 | - (this.data.charCodeAt(offset + 0) & 0xff); - break; - case 2: - return (this.data.charCodeAt(offset + 1) & 0xff) << 8 | - (this.data.charCodeAt(offset + 0) & 0xff); - break; - default: - return this.data.charCodeAt(offset) & 0xff; - break; - } - }; - - this.getDOSDate = function(dosdate, dostime) { - var day = dosdate & 0x1f; - var month = ((dosdate >> 5) & 0xf) - 1; - var year = 1980 + ((dosdate >> 9) & 0x7f) - var second = (dostime & 0x1f) * 2; - var minute = (dostime >> 5) & 0x3f; - hour = (dostime >> 11) & 0x1f; - return new Date(year, month, day, hour, minute, second); - } - - this.open = function(data) { - this.data = data; - this.files = []; - - if (this.data.length < 22) - return { 'status' : false, 'error' : 'Invalid data' }; - var endOfCentralDirectory = this.data.length - 22; - while (endOfCentralDirectory >= 0 && this.getInt(endOfCentralDirectory, 4) != 0x06054b50) - --endOfCentralDirectory; - if (endOfCentralDirectory < 0) - return { 'status' : false, 'error' : 'Invalid data' }; - if (this.getInt(endOfCentralDirectory + 4, 2) != 0 || this.getInt(endOfCentralDirectory + 6, 2) != 0) - return { 'status' : false, 'error' : 'No multidisk support' }; - - var entriesInThisDisk = this.getInt(endOfCentralDirectory + 8, 2); - var centralDirectoryOffset = this.getInt(endOfCentralDirectory + 16, 4); - var globalCommentLength = this.getInt(endOfCentralDirectory + 20, 2); - this.comment = this.data.slice(endOfCentralDirectory + 22, endOfCentralDirectory + 22 + globalCommentLength); - - var fileOffset = centralDirectoryOffset; - - for (var i = 0; i < entriesInThisDisk; ++i) { - if (this.getInt(fileOffset + 0, 4) != 0x02014b50) - return { 'status' : false, 'error' : 'Invalid data' }; - if (this.getInt(fileOffset + 6, 2) > 20) - return { 'status' : false, 'error' : 'Unsupported version' }; - if (this.getInt(fileOffset + 8, 2) & 1) - return { 'status' : false, 'error' : 'Encryption not implemented' }; - - var compressionMethod = this.getInt(fileOffset + 10, 2); - if (compressionMethod != 0 && compressionMethod != 8) - return { 'status' : false, 'error' : 'Unsupported compression method' }; - - var lastModFileTime = this.getInt(fileOffset + 12, 2); - var lastModFileDate = this.getInt(fileOffset + 14, 2); - var lastModifiedDate = this.getDOSDate(lastModFileDate, lastModFileTime); - - var crc = this.getInt(fileOffset + 16, 4); - // TODO: crc - - var compressedSize = this.getInt(fileOffset + 20, 4); - var uncompressedSize = this.getInt(fileOffset + 24, 4); - - var fileNameLength = this.getInt(fileOffset + 28, 2); - var extraFieldLength = this.getInt(fileOffset + 30, 2); - var fileCommentLength = this.getInt(fileOffset + 32, 2); - - var relativeOffsetOfLocalHeader = this.getInt(fileOffset + 42, 4); - - var fileName = this.data.slice(fileOffset + 46, fileOffset + 46 + fileNameLength); - var fileComment = this.data.slice(fileOffset + 46 + fileNameLength + extraFieldLength, fileOffset + 46 + fileNameLength + extraFieldLength + fileCommentLength); - - if (this.getInt(relativeOffsetOfLocalHeader + 0, 4) != 0x04034b50) - return { 'status' : false, 'error' : 'Invalid data' }; - var localFileNameLength = this.getInt(relativeOffsetOfLocalHeader + 26, 2); - var localExtraFieldLength = this.getInt(relativeOffsetOfLocalHeader + 28, 2); - var localFileContent = relativeOffsetOfLocalHeader + 30 + localFileNameLength + localExtraFieldLength; - - this.files[fileName] = - { - 'fileComment' : fileComment, - 'compressionMethod' : compressionMethod, - 'compressedSize' : compressedSize, - 'uncompressedSize' : uncompressedSize, - 'localFileContent' : localFileContent, - 'lastModifiedDate' : lastModifiedDate - }; - - fileOffset += 46 + fileNameLength + extraFieldLength + fileCommentLength; - } - return { 'status' : true } - }; - - - this.read = function(fileName) { - var fileInfo = this.files[fileName]; - if (fileInfo) { - if (fileInfo.compressionMethod == 8) { - if (!tinf) { - tinf = new TINF(); - tinf.init(); - } - var result = tinf.uncompress(this.data, fileInfo.localFileContent); - if (result.status == tinf.OK) - return { 'status' : true, 'data' : result.data }; - else - return { 'status' : false, 'error' : result.error }; - } else { - return { 'status' : true, 'data' : this.data.slice(fileInfo.localFileContent, fileInfo.localFileContent + fileInfo.uncompressedSize) }; - } - } - return { 'status' : false, 'error' : "File '" + fileName + "' doesn't exist in zip" }; - }; - -}; - - - -/* - * tinflate - tiny inflate - * - * Copyright (c) 2003 by Joergen Ibsen / Jibz - * All Rights Reserved - * - * http://www.ibsensoftware.com/ - * - * This software is provided 'as-is', without any express - * or implied warranty. In no event will the authors be - * held liable for any damages arising from the use of - * this software. - * - * Permission is granted to anyone to use this software - * for any purpose, including commercial applications, - * and to alter it and redistribute it freely, subject to - * the following restrictions: - * - * 1. The origin of this software must not be - * misrepresented; you must not claim that you - * wrote the original software. If you use this - * software in a product, an acknowledgment in - * the product documentation would be appreciated - * but is not required. - * - * 2. Altered source versions must be plainly marked - * as such, and must not be misrepresented as - * being the original software. - * - * 3. This notice may not be removed or altered from - * any source distribution. - */ - -/* - * tinflate javascript port by Erik Moller in May 2011. - * emoller@opera.com - * - * read_bits() patched by mike@imidio.com to allow - * reading more then 8 bits (needed in some zlib streams) - */ - -"use strict"; - -function TINF() { - -this.OK = 0; -this.DATA_ERROR = (-3); -this.WINDOW_SIZE = 32768; - -/* ------------------------------ * - * -- internal data structures -- * - * ------------------------------ */ - -this.TREE = function() { - this.table = new Array(16); /* table of code length counts */ - this.trans = new Array(288); /* code -> symbol translation table */ -}; - -this.DATA = function(that) { - this.source = ''; - this.sourceIndex = 0; - this.tag = 0; - this.bitcount = 0; - - this.dest = []; - - this.history = []; - - this.ltree = new that.TREE(); /* dynamic length/symbol tree */ - this.dtree = new that.TREE(); /* dynamic distance tree */ -}; - -/* --------------------------------------------------- * - * -- uninitialized global data (static structures) -- * - * --------------------------------------------------- */ - -this.sltree = new this.TREE(); /* fixed length/symbol tree */ -this.sdtree = new this.TREE(); /* fixed distance tree */ - -/* extra bits and base tables for length codes */ -this.length_bits = new Array(30); -this.length_base = new Array(30); - -/* extra bits and base tables for distance codes */ -this.dist_bits = new Array(30); -this.dist_base = new Array(30); - -/* special ordering of code length codes */ -this.clcidx = [ - 16, 17, 18, 0, 8, 7, 9, 6, - 10, 5, 11, 4, 12, 3, 13, 2, - 14, 1, 15 -]; - -/* ----------------------- * - * -- utility functions -- * - * ----------------------- */ - -/* build extra bits and base tables */ -this.build_bits_base = function(bits, base, delta, first) -{ - var i, sum; - - /* build bits table */ - for (i = 0; i < delta; ++i) bits[i] = 0; - for (i = 0; i < 30 - delta; ++i) bits[i + delta] = Math.floor(i / delta); - - /* build base table */ - for (sum = first, i = 0; i < 30; ++i) - { - base[i] = sum; - sum += 1 << bits[i]; - } -} - -/* build the fixed huffman trees */ -this.build_fixed_trees = function(lt, dt) -{ - var i; - - /* build fixed length tree */ - for (i = 0; i < 7; ++i) lt.table[i] = 0; - - lt.table[7] = 24; - lt.table[8] = 152; - lt.table[9] = 112; - - for (i = 0; i < 24; ++i) lt.trans[i] = 256 + i; - for (i = 0; i < 144; ++i) lt.trans[24 + i] = i; - for (i = 0; i < 8; ++i) lt.trans[24 + 144 + i] = 280 + i; - for (i = 0; i < 112; ++i) lt.trans[24 + 144 + 8 + i] = 144 + i; - - /* build fixed distance tree */ - for (i = 0; i < 5; ++i) dt.table[i] = 0; - - dt.table[5] = 32; - - for (i = 0; i < 32; ++i) dt.trans[i] = i; -} - -/* given an array of code lengths, build a tree */ -this.build_tree = function(t, lengths, loffset, num) -{ - var offs = new Array(16); - var i, sum; - - /* clear code length count table */ - for (i = 0; i < 16; ++i) t.table[i] = 0; - - /* scan symbol lengths, and sum code length counts */ - for (i = 0; i < num; ++i) t.table[lengths[loffset + i]]++; - - t.table[0] = 0; - - /* compute offset table for distribution sort */ - for (sum = 0, i = 0; i < 16; ++i) - { - offs[i] = sum; - sum += t.table[i]; - } - - /* create code->symbol translation table (symbols sorted by code) */ - for (i = 0; i < num; ++i) - { - if (lengths[loffset + i]) t.trans[offs[lengths[loffset + i]]++] = i; - } -} - -/* ---------------------- * - * -- decode functions -- * - * ---------------------- */ - -/* get one bit from source stream */ -this.getbit = function(d) -{ - var bit; - - /* check if tag is empty */ - if (!d.bitcount--) - { - /* load next tag */ - d.tag = d.source[d.sourceIndex++] & 0xff; - d.bitcount = 7; - } - - /* shift bit out of tag */ - bit = d.tag & 0x01; - d.tag >>= 1; - - return bit; -} - -/* read a num bit value from a stream and add base */ -function read_bits_direct(source, bitcount, tag, idx, num) -{ - var val = 0; - while (bitcount < 24) { - tag = tag | (source[idx++] & 0xff) << bitcount; - bitcount += 8; - } - val = tag & (0xffff >> (16 - num)); - tag >>= num; - bitcount -= num; - return [bitcount, tag, idx, val]; -} -this.read_bits = function(d, num, base) -{ - if (!num) - return base; - - var ret = read_bits_direct(d.source, d.bitcount, d.tag, d.sourceIndex, num); - d.bitcount = ret[0]; - d.tag = ret[1]; - d.sourceIndex = ret[2]; - return ret[3] + base; -} - -/* given a data stream and a tree, decode a symbol */ -this.decode_symbol = function(d, t) -{ - while (d.bitcount < 16) { - d.tag = d.tag | (d.source[d.sourceIndex++] & 0xff) << d.bitcount; - d.bitcount += 8; - } - - var sum = 0, cur = 0, len = 0; - do { - cur = 2 * cur + ((d.tag & (1 << len)) >> len); - - ++len; - - sum += t.table[len]; - cur -= t.table[len]; - - } while (cur >= 0); - - d.tag >>= len; - d.bitcount -= len; - - return t.trans[sum + cur]; -} - -/* given a data stream, decode dynamic trees from it */ -this.decode_trees = function(d, lt, dt) -{ - var code_tree = new this.TREE(); - var lengths = new Array(288+32); - var hlit, hdist, hclen; - var i, num, length; - - /* get 5 bits HLIT (257-286) */ - hlit = this.read_bits(d, 5, 257); - - /* get 5 bits HDIST (1-32) */ - hdist = this.read_bits(d, 5, 1); - - /* get 4 bits HCLEN (4-19) */ - hclen = this.read_bits(d, 4, 4); - - for (i = 0; i < 19; ++i) lengths[i] = 0; - - /* read code lengths for code length alphabet */ - for (i = 0; i < hclen; ++i) - { - /* get 3 bits code length (0-7) */ - var clen = this.read_bits(d, 3, 0); - - lengths[this.clcidx[i]] = clen; - } - - /* build code length tree */ - this.build_tree(code_tree, lengths, 0, 19); - - /* decode code lengths for the dynamic trees */ - for (num = 0; num < hlit + hdist; ) - { - var sym = this.decode_symbol(d, code_tree); - - switch (sym) - { - case 16: - /* copy previous code length 3-6 times (read 2 bits) */ - { - var prev = lengths[num - 1]; - for (length = this.read_bits(d, 2, 3); length; --length) - { - lengths[num++] = prev; - } - } - break; - case 17: - /* repeat code length 0 for 3-10 times (read 3 bits) */ - for (length = this.read_bits(d, 3, 3); length; --length) - { - lengths[num++] = 0; - } - break; - case 18: - /* repeat code length 0 for 11-138 times (read 7 bits) */ - for (length = this.read_bits(d, 7, 11); length; --length) - { - lengths[num++] = 0; - } - break; - default: - /* values 0-15 represent the actual code lengths */ - lengths[num++] = sym; - break; - } - } - - /* build dynamic trees */ - this.build_tree(lt, lengths, 0, hlit); - this.build_tree(dt, lengths, hlit, hdist); -} - -/* ----------------------------- * - * -- block inflate functions -- * - * ----------------------------- */ - -/* given a stream and two trees, inflate a block of data */ -this.inflate_block_data = function(d, lt, dt) -{ - // js optimization. - var ddest = d.dest; - var ddestlength = ddest.length; - - while (1) - { - var sym = this.decode_symbol(d, lt); - - /* check for end of block */ - if (sym == 256) - { - return this.OK; - } - - if (sym < 256) - { - ddest[ddestlength++] = sym; // ? String.fromCharCode(sym); - d.history.push(sym); - } else { - - var length, dist, offs; - var i; - - sym -= 257; - - /* possibly get more bits from length code */ - length = this.read_bits(d, this.length_bits[sym], this.length_base[sym]); - - dist = this.decode_symbol(d, dt); - - /* possibly get more bits from distance code */ - offs = d.history.length - this.read_bits(d, this.dist_bits[dist], this.dist_base[dist]); - - if (offs < 0) - throw ("Invalid zlib offset " + offs); - - /* copy match */ - for (i = offs; i < offs + length; ++i) { - //ddest[ddestlength++] = ddest[i]; - ddest[ddestlength++] = d.history[i]; - d.history.push(d.history[i]); - } - } - } -} - -/* inflate an uncompressed block of data */ -this.inflate_uncompressed_block = function(d) -{ - var length, invlength; - var i; - - if (d.bitcount > 7) { - var overflow = Math.floor(d.bitcount / 8); - d.sourceIndex -= overflow; - d.bitcount = 0; - d.tag = 0; - } - - /* get length */ - length = d.source[d.sourceIndex+1]; - length = 256*length + d.source[d.sourceIndex]; - - /* get one's complement of length */ - invlength = d.source[d.sourceIndex+3]; - invlength = 256*invlength + d.source[d.sourceIndex+2]; - - /* check length */ - if (length != (~invlength & 0x0000ffff)) return this.DATA_ERROR; - - d.sourceIndex += 4; - - /* copy block */ - for (i = length; i; --i) { - d.history.push(d.source[d.sourceIndex]); - d.dest[d.dest.length] = d.source[d.sourceIndex++]; - } - - /* make sure we start next block on a byte boundary */ - d.bitcount = 0; - - return this.OK; -} - -/* inflate a block of data compressed with fixed huffman trees */ -this.inflate_fixed_block = function(d) -{ - /* decode block using fixed trees */ - return this.inflate_block_data(d, this.sltree, this.sdtree); -} - -/* inflate a block of data compressed with dynamic huffman trees */ -this.inflate_dynamic_block = function(d) -{ - /* decode trees from stream */ - this.decode_trees(d, d.ltree, d.dtree); - - /* decode block using decoded trees */ - return this.inflate_block_data(d, d.ltree, d.dtree); -} - -/* ---------------------- * - * -- public functions -- * - * ---------------------- */ - -/* initialize global (static) data */ -this.init = function() -{ - /* build fixed huffman trees */ - this.build_fixed_trees(this.sltree, this.sdtree); - - /* build extra bits and base tables */ - this.build_bits_base(this.length_bits, this.length_base, 4, 3); - this.build_bits_base(this.dist_bits, this.dist_base, 2, 1); - - /* fix a special case */ - this.length_bits[28] = 0; - this.length_base[28] = 258; - - this.reset(); -} - -this.reset = function() -{ - this.d = new this.DATA(this); - delete this.header; -} - -/* inflate stream from source to dest */ -this.uncompress = function(source, offset) -{ - - var d = this.d; - var bfinal; - - /* initialise data */ - d.source = source; - d.sourceIndex = offset; - d.bitcount = 0; - - d.dest = []; - - // Skip zlib header at start of stream - if (typeof this.header == 'undefined') { - this.header = this.read_bits(d, 16, 0); - /* byte 0: 0x78, 7 = 32k window size, 8 = deflate */ - /* byte 1: check bits for header and other flags */ - } - - var blocks = 0; - - do { - - var btype; - var res; - - /* read final block flag */ - bfinal = this.getbit(d); - - /* read block type (2 bits) */ - btype = this.read_bits(d, 2, 0); - - /* decompress block */ - switch (btype) - { - case 0: - /* decompress uncompressed block */ - res = this.inflate_uncompressed_block(d); - break; - case 1: - /* decompress block with fixed huffman trees */ - res = this.inflate_fixed_block(d); - break; - case 2: - /* decompress block with dynamic huffman trees */ - res = this.inflate_dynamic_block(d); - break; - default: - return { 'status' : this.DATA_ERROR }; - } - - if (res != this.OK) return { 'status' : this.DATA_ERROR }; - blocks++; - - } while (!bfinal && d.sourceIndex < d.source.length); - - d.history = d.history.slice(-this.WINDOW_SIZE); - - return { 'status' : this.OK, 'data' : d.dest }; -} - -}; diff --git a/plugins/dynamix.vm.manager/include/rfb.js b/plugins/dynamix.vm.manager/include/rfb.js index b45537c7b..69449bfee 100644 --- a/plugins/dynamix.vm.manager/include/rfb.js +++ b/plugins/dynamix.vm.manager/include/rfb.js @@ -374,8 +374,6 @@ var RFB; } for (i = 0; i < 4; i++) { - //this._FBU.zlibs[i] = new TINF(); - //this._FBU.zlibs[i].init(); this._FBU.zlibs[i] = new inflator.Inflate(); } }, @@ -739,6 +737,7 @@ var RFB; // an RFB state change and a UI interface issue this._updateState('password', "Password Required"); this._onPasswordRequired(this); + return false; } if (this._sock.rQwait("auth challenge", 16)) { return false; } @@ -921,18 +920,17 @@ var RFB; var totalMessagesLength = (numServerMessages + numClientMessages + numEncodings) * 16; if (this._sock.rQwait('TightVNC extended server init header', totalMessagesLength, 32 + name_length)) { return false; } - var i; - for (i = 0; i < numServerMessages; i++) { - var srvMsg = this._sock.rQshiftStr(16); - } + // we don't actually do anything with the capability information that TIGHT sends, + // so we just skip the all of this. - for (i = 0; i < numClientMessages; i++) { - var clientMsg = this._sock.rQshiftStr(16); - } + // TIGHT server message capabilities + this._sock.rQskipBytes(16 * numServerMessages); - for (i = 0; i < numEncodings; i++) { - var encoding = this._sock.rQshiftStr(16); - } + // TIGHT client message capabilities + this._sock.rQskipBytes(16 * numClientMessages); + + // TIGHT encoding capabilities + this._sock.rQskipBytes(16 * numEncodings); } // NB(directxman12): these are down here so that we don't run them multiple times @@ -1688,7 +1686,7 @@ var RFB; var resetStreams = 0; var streamId = -1; - var decompress = function (data) { + var decompress = function (data, expected) { for (var i = 0; i < 4; i++) { if ((resetStreams >> i) & 1) { this._FBU.zlibs[i].reset(); @@ -1697,7 +1695,7 @@ var RFB; } //var uncompressed = this._FBU.zlibs[streamId].uncompress(data, 0); - var uncompressed = this._FBU.zlibs[streamId].inflate(data, true); + var uncompressed = this._FBU.zlibs[streamId].inflate(data, true, expected); /*if (uncompressed.status !== 0) { Util.Error("Invalid data in zlib stream"); }*/ @@ -1830,7 +1828,7 @@ var RFB; if (raw) { data = this._sock.rQshiftBytes(cl_data); } else { - data = decompress(this._sock.rQshiftBytes(cl_data)); + data = decompress(this._sock.rQshiftBytes(cl_data), rowSize * this._FBU.height); } // Convert indexed (palette based) image data to RGB @@ -1879,7 +1877,7 @@ var RFB; if (raw) { data = this._sock.rQshiftBytes(cl_data); } else { - data = decompress(this._sock.rQshiftBytes(cl_data)); + data = decompress(this._sock.rQshiftBytes(cl_data), uncompressedSize); } this._display.blitRgbImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, data, 0, false); diff --git a/plugins/dynamix.vm.manager/include/ui.js b/plugins/dynamix.vm.manager/include/ui.js index f3b5fe416..a1c3e5c50 100644 --- a/plugins/dynamix.vm.manager/include/ui.js +++ b/plugins/dynamix.vm.manager/include/ui.js @@ -15,8 +15,6 @@ var UI; (function () { "use strict"; - var resizeTimeout; - // Load supporting scripts window.onscriptsload = function () { UI.load(); }; Util.load_scripts(["webutil.js", "base64.js", "websock.js", "des.js", @@ -26,6 +24,7 @@ var UI; UI = { rfb_state : 'loaded', + resizeTimeout: null, settingsOpen : false, connSettingsOpen : false, popupStatusTimeout: null, @@ -97,8 +96,9 @@ var UI; UI.initSetting('view_only', false); UI.initSetting('path', 'websockify'); UI.initSetting('repeaterID', ''); + UI.initSetting('token', ''); - var autoconnect = WebUtil.getQueryVar('autoconnect', false); + var autoconnect = WebUtil.getConfigVar('autoconnect', false); if (autoconnect === 'true' || autoconnect == '1') { autoconnect = true; UI.connect(); @@ -253,8 +253,8 @@ var UI; // When the local window has been resized, wait until the size remains // the same for 0.5 seconds before sending the request for changing // the resolution of the session - clearTimeout(resizeTimeout); - resizeTimeout = setTimeout(function(){ + clearTimeout(UI.resizeTimeout); + UI.resizeTimeout = setTimeout(function(){ display.set_maxWidth(size.w); display.set_maxHeight(size.h); Util.Debug('Attempting setDesktopSize(' + @@ -358,7 +358,7 @@ var UI; // Initial page load read/initialization of settings initSetting: function(name, defVal) { // Check Query string followed by cookie - var val = WebUtil.getQueryVar(name); + var val = WebUtil.getConfigVar(name); if (val === null) { val = WebUtil.readSetting(name, defVal); } @@ -519,6 +519,7 @@ var UI; UI.connSettingsOpen = false; UI.saveSetting('host'); UI.saveSetting('port'); + UI.saveSetting('token'); //UI.saveSetting('password'); } else { $D('noVNC_controls').style.display = "block"; @@ -812,7 +813,14 @@ var UI; var host = $D('noVNC_host').value; var port = $D('noVNC_port').value; var password = $D('noVNC_password').value; + var token = $D('noVNC_token').value; var path = $D('noVNC_path').value; + + //if token is in path then ignore the new token variable + if (token) { + path = WebUtil.injectParamIfMissing(path, "token", token); + } + if ((!host) || (!port)) { throw new Error("Must set host and port"); } diff --git a/plugins/dynamix.vm.manager/include/websock.js b/plugins/dynamix.vm.manager/include/websock.js index 892238b5e..f3336a0a8 100644 --- a/plugins/dynamix.vm.manager/include/websock.js +++ b/plugins/dynamix.vm.manager/include/websock.js @@ -66,6 +66,12 @@ function Websock() { (function () { "use strict"; + // this has performance issues in some versions Chromium, and + // doesn't gain a tremendous amount of performance increase in Firefox + // at the moment. It may be valuable to turn it on in the future. + var ENABLE_COPYWITHIN = false; + + var MAX_RQ_GROW_SIZE = 40 * 1024 * 1024; // 40 MiB var typedArrayToString = (function () { // This is only for PhantomJS, which doesn't like apply-ing @@ -340,9 +346,49 @@ function Websock() { return new Uint8Array(this._sQ.buffer, 0, this._sQlen); }, + _expand_compact_rQ: function (min_fit) { + var resizeNeeded = min_fit || this._rQlen - this._rQi > this._rQbufferSize / 2; + if (resizeNeeded) { + if (!min_fit) { + // just double the size if we need to do compaction + this._rQbufferSize *= 2; + } else { + // otherwise, make sure we satisy rQlen - rQi + min_fit < rQbufferSize / 8 + this._rQbufferSize = (this._rQlen - this._rQi + min_fit) * 8; + } + } + + // we don't want to grow unboundedly + if (this._rQbufferSize > MAX_RQ_GROW_SIZE) { + this._rQbufferSize = MAX_RQ_GROW_SIZE; + if (this._rQbufferSize - this._rQlen - this._rQi < min_fit) { + throw new Exception("Receive Queue buffer exceeded " + MAX_RQ_GROW_SIZE + " bytes, and the new message could not fit"); + } + } + + if (resizeNeeded) { + var old_rQbuffer = this._rQ.buffer; + this._rQmax = this._rQbufferSize / 8; + this._rQ = new Uint8Array(this._rQbufferSize); + this._rQ.set(new Uint8Array(old_rQbuffer, this._rQi)); + } else { + if (ENABLE_COPYWITHIN) { + this._rQ.copyWithin(0, this._rQi); + } else { + this._rQ.set(new Uint8Array(this._rQ.buffer, this._rQi)); + } + } + + this._rQlen = this._rQlen - this._rQi; + this._rQi = 0; + }, + _decode_message: function (data) { // push arraybuffer values onto the end var u8 = new Uint8Array(data); + if (u8.length > this._rQbufferSize - this._rQlen) { + this._expand_compact_rQ(u8.length); + } this._rQ.set(u8, this._rQlen); this._rQlen += u8.length; }, @@ -357,23 +403,7 @@ function Websock() { this._rQlen = 0; this._rQi = 0; } else if (this._rQlen > this._rQmax) { - if (this._rQlen - this._rQi > 0.5 * this._rQbufferSize) { - var old_rQbuffer = this._rQ.buffer; - this._rQbufferSize *= 2; - this._rQmax = this._rQbufferSize / 8; - this._rQ = new Uint8Array(this._rQbufferSize); - this._rQ.set(new Uint8Array(old_rQbuffer, this._rQi)); - } else { - if (this._rQ.copyWithin) { - // Firefox only, ATM - this._rQ.copyWithin(0, this._rQi); - } else { - this._rQ.set(new Uint8Array(this._rQ.buffer, this._rQi)); - } - } - - this._rQlen = this._rQlen - this._rQi; - this._rQi = 0; + this._expand_compact_rQ(); } } else { Util.Debug("Ignoring empty message"); diff --git a/plugins/dynamix.vm.manager/include/webutil.js b/plugins/dynamix.vm.manager/include/webutil.js index e674bf94f..4289aa6bd 100644 --- a/plugins/dynamix.vm.manager/include/webutil.js +++ b/plugins/dynamix.vm.manager/include/webutil.js @@ -90,6 +90,29 @@ WebUtil.getQueryVar = function (name, defVal) { } }; +// Read a hash fragment variable +WebUtil.getHashVar = function (name, defVal) { + "use strict"; + var re = new RegExp('.*[&#]' + name + '=([^&]*)'), + match = document.location.hash.match(re); + if (typeof defVal === 'undefined') { defVal = null; } + if (match) { + return decodeURIComponent(match[1]); + } else { + return defVal; + } +}; + +// Read a variable from the fragment or the query string +// Fragment takes precedence +WebUtil.getConfigVar = function (name, defVal) { + "use strict"; + var val = WebUtil.getHashVar(name); + if (val === null) { + val = WebUtil.getQueryVar(name, defVal); + } + return val; +}; /* * Cookie handling. Dervied from: http://www.quirksmode.org/js/cookies.html @@ -237,3 +260,27 @@ WebUtil.selectStylesheet = function (sheet) { } return sheet; }; + +WebUtil.injectParamIfMissing = function (path, param, value) { + // force pretend that we're dealing with a relative path + // (assume that we wanted an extra if we pass one in) + path = "/" + path; + + var elem = document.createElement('a'); + elem.href = path; + + var param_eq = encodeURIComponent(param) + "="; + var query; + if (elem.search) { + query = elem.search.slice(1).split('&'); + } else { + query = []; + } + + if (!query.some(function (v) { return v.startsWith(param_eq); })) { + query.push(param_eq + encodeURIComponent(value)); + elem.search = "?" + query.join("&"); + } + + return elem.pathname.slice(1) + elem.search + elem.hash; +}; diff --git a/plugins/dynamix.vm.manager/vnc.html b/plugins/dynamix.vm.manager/vnc.html index 0ec5e603d..fa7c2e986 100644 --- a/plugins/dynamix.vm.manager/vnc.html +++ b/plugins/dynamix.vm.manager/vnc.html @@ -11,6 +11,8 @@ Connect parameters are provided in query string: http://example.com/?host=HOST&port=PORT&encrypt=1&true_color=1 + or the fragment: + http://example.com/#host=HOST&port=PORT&encrypt=1&true_color=1 --> noVNC @@ -197,6 +199,7 @@
  • +
  • diff --git a/plugins/dynamix/ArrayDevices.page b/plugins/dynamix/ArrayDevices.page index 340636979..a91db041a 100644 --- a/plugins/dynamix/ArrayDevices.page +++ b/plugins/dynamix/ArrayDevices.page @@ -17,10 +17,10 @@ Title="Array Devices" var timer = null; function array_status() { - $.post('/webGui/include/DeviceList.php',{path:'',device:'array',width:window.innerWidth,timer:timer},function(data) { + $.post('/webGui/include/DeviceList.php',{path:'',device:'array'},function(data) { if (data) $('#array_devices').html(data); 0 || ($display['refresh']<0 && $var['mdResync']==0)) && $var['fsState']=='Started'):?> - + if ($('#tab1').is(':checked')) timer = setTimeout(array_status,); setTimeout(array_status,); @@ -40,7 +40,7 @@ array_status();  "; endforeach; if ($display['total']) echo " "; diff --git a/plugins/dynamix/ArrayOperation.page b/plugins/dynamix/ArrayOperation.page index ccfb061d0..5f25e9359 100644 --- a/plugins/dynamix/ArrayOperation.page +++ b/plugins/dynamix/ArrayOperation.page @@ -14,21 +14,41 @@ Title="Array Operation" */ ?> +"; + echo ""; + echo "Maintenance mode"; + echo "Maintenance mode - if checked, Start array but do not mount disks."; + echo ""; +} +function status_indicator() { + global $var; + $ball = "/webGui/images/{$var['mdColor']}.png"; + switch ($var['mdColor']) { + case 'green-on': $help = 'Started, array protected'; break; + case 'green-blink': $help = 'Stopped'; break; + case 'yellow-on': $help = 'Started, array unprotected'; break; + case 'yellow-blink': $help = 'Stopped'; break; + } + return "$help"; +} +?> -"; - echo ""; - echo "Maintenance mode"; - echo "Maintenance mode - if checked, Start array but do not mount disks."; - echo ""; -} -function status_indicator() { - global $var; - $ball = "/webGui/images/{$var['mdColor']}.png"; - switch ($var['mdColor']) { - case 'green-on': $help = 'Started, array protected'; break; - case 'green-blink': $help = 'Stopped'; break; - case 'yellow-on': $help = 'Started, array unprotected'; break; - case 'yellow-blink': $help = 'Stopped'; break; - } - return "$help"; -} -?>
    @@ -143,9 +143,9 @@ function status_indicator() { if ($var['sbSyncExit']!=0):?> - + +
    Error code: @@ -156,15 +156,24 @@ function status_indicator() { - - - - + + + + - + +
    Duration: + if (strpos($disks['parity']['status'],"DISK_NP")===0 && (empty($disks['parity2']) || strpos($disks['parity2']['status'],"DISK_NP")===0)):?> diff --git a/plugins/dynamix/BootDevice.page b/plugins/dynamix/BootDevice.page index e052381e6..804e967b9 100644 --- a/plugins/dynamix/BootDevice.page +++ b/plugins/dynamix/BootDevice.page @@ -15,10 +15,10 @@ Title="Boot Device" ?>
    Last check incomplete on , finding error. -
    Error code:
    Last checked , finding error.
    Last checked on , finding error. +
    Duration: + +
    Last check incomplete on , finding error. +
    Error code: + +
    Last check completed on , finding error. -
    Duration:
    Stopped. Configuration valid.
    -"); $i = 1; -foreach ($disks as $disk): - switch ($disk['type']): - case 'Parity': - if ($disk['status']!='DISK_NP') $row0[0] = ''; - break; - case 'Data': - case 'Cache': - if ($disk['status']!='DISK_NP') $row0[$i++] = ""; - break; - endswitch; -endforeach; -foreach ($devs as $dev): +$slots = max(count($disks)+count($devs)-1, 25); +$row0 = array_fill(0,$slots,""); $i = 0; +foreach ($disks as $disk) + if ($disk['type']=='Parity' && $disk['status']!='DISK_NP') + $row0[$i++] = ""; +foreach ($disks as $disk) + if ($disk['type']=='Data' && $disk['status']!='DISK_NP') + $row0[$i++] = ""; +foreach ($disks as $disk) + if ($disk['type']=='Cache' && $disk['status']!='DISK_NP') + $row0[$i++] = ""; +foreach ($devs as $dev) $row0[$i++] = ""; -endforeach; echo "".implode('',$row0); ?> - - - - - - - + + + + + + + diff --git a/plugins/dynamix/DashboardApps.page b/plugins/dynamix/DashboardApps.page index afee5d658..a91185f5c 100644 --- a/plugins/dynamix/DashboardApps.page +++ b/plugins/dynamix/DashboardApps.page @@ -44,7 +44,7 @@ div.Panel:hover{overflow:visible;z-index:10;} get_domains(); if (is_array($doms)) { @@ -266,7 +266,7 @@ function addVMContext(name, uuid, template, state, vncurl, log){ if (state == "shutoff") { opts.push({text: "Edit", icon: "fa-pencil", href: path+'/UpdateVM?uuid='+uuid }); - opts.push({text: "Edit XML", icon: "fa-code", href: path+'/UpdateVM?template=XML_Expert&uuid='+uuid }); + opts.push({text: "Edit XML", icon: "fa-code", href: path+'/UpdateVM?template=Custom&uuid='+uuid }); opts.push({divider: true}); @@ -284,7 +284,7 @@ function addVMContext(name, uuid, template, state, vncurl, log){ } else { - opts.push({text: "View XML", icon: "fa-code", href: path+'/UpdateVM?template=XML_Expert&uuid='+uuid }); + opts.push({text: "View XML", icon: "fa-code", href: path+'/UpdateVM?template=Custom&uuid='+uuid }); } diff --git a/plugins/dynamix/DeviceAttributes.page b/plugins/dynamix/DeviceAttributes.page index dd62fc9da..013bde830 100644 --- a/plugins/dynamix/DeviceAttributes.page +++ b/plugins/dynamix/DeviceAttributes.page @@ -1,4 +1,4 @@ -Menu="Device" +Menu="Device New" Title="Attributes" Cond="strpos($disks[$name]['status'],'_NP')===false" --- @@ -14,10 +14,9 @@ Cond="strpos($disks[$name]['status'],'_NP')===false" * all copies or substantial portions of the Software. */ ?> - - - + Name: : @@ -188,7 +133,7 @@ File system type: -Spin down delay: +Spin down delay: : + + +Warning disk utilization level (%): +: + +> *Warning disk utilization* sets the warning threshold for this hard disk utilization. Exceeding this threshold will result in a warning notification. +> +> When the warning level is set equal or greater than the critical level, there will be only critical notifications (warnings are not existing). + +Critical disk utilization level (%): +: + +> *Critical disk utilization* sets the critical threshold for this hard disk utilization. Exceeding this threshold will result in an alert notification. + +Warning disk temperature threshold (°): +: + +> *Warning disk temperature* sets the warning threshold for this hard disk temperature. Exceeding this threshold will result in a warning notification. + +Critical disk temperature threshold (°): +: + +> *Critical disk temperature* sets the critical threshold for this hard disk temperature. Exceeding this threshold will result in an alert notification. + @@ -215,10 +183,9 @@ Spinup group(s):   : - -1):?> +1):?>
    Pool Information
    btrfs filesystem show: @@ -421,53 +388,78 @@ xfs_repair status: -
    Self-Test
    -
    -Download SMART report: -: disabled> +
    SMART Settings
    -SMART self-test history: -: +
    + + + + + +SMART notification value: +: -> Press **Show** to view the self-test history as is kept on the disk itself. -> This feature is only available when the disk is in active mode. - - - -SMART error log: -: - -> Press **Show** to view the error report as is kept on the disk itself. -> This feature is only available when the disk is in active mode. - - - -SMART short self-test: -: - -> Starts a *short* SMART self-test, the estimated duration can be viewed under the *Capabilities* section. This is usually a few minutes. +> SMART notifications are generated on either an increasing RAW value of the attribute, or a decreasing NORMALIZED value which reaches a predefined threshold set by the manufacturer. > -> When the disk is spun down, it will abort any running self-test. -> This feature is only available when the disk is in active mode. +> Each disk may have its own specific setting overruling the 'default' setting (see global SMART settings under Disk Settings). -SMART extended self-test: -: +SMART notification tolerance level: +: -> Starts an *extended* SMART self-test, the estimated duration can be viewed under the *Capabilities* section. This is usually several hours. +> A tolerance level may be given to prevent that small changes result in a notification. Setting a too high tolerance level may result in critical changes without a notification. > -> When the disk is spun down, it will abort any running self-test. It is advised to disable the spin down timer of the disk -> to avoid interruption of this self-test. +> Each disk may have its own specific setting overruling the 'default' setting (see global SMART settings under Disk Settings). + +SMART controller type: +: + + + + + +> By default automatic controller selection is done by smartctl to read the SMART information. Certain controllers however need specific settings for smartctl to work. +> Use this setting to select your controller type and fill-in the specific disk index and device name for your situation. Use the manufacturer's documentation to find the relevant information. > -> This feature is only available when the disk is in active mode. +> Each disk may have its own specific setting overruling the 'default' setting (see global SMART settings under Disk Settings). -Last SMART test result: - -: - -: --- - +SMART attribute notifications: +: Custom attributes (use comma to separate numbers) -> When no test is running it will show here the latest obtained self-test result (if available). -> Otherwise a progress indicator (percentage value) is shown for a running test. + +  +: > + -
    +> The user can enable or disable notifications for the given SMART attributes. It is recommended to keep the default, which is ALL selected attributes, +> when certain attributes are not present on your hard disk or do not provide the correct information, these may be excluded. +> In addition custom SMART attributes can be entered to generate notifications. Be careful in this selection, +> it may cause an avalance of notifcations if inappropriate SMART attributes are chosen. +> +> Each disk may have its own specific setting overruling the 'default' setting (see global SMART settings under Disk Settings). + + +: + diff --git a/plugins/dynamix/DiskList.page b/plugins/dynamix/DiskList.page index 71f543958..7bafa248d 100644 --- a/plugins/dynamix/DiskList.page +++ b/plugins/dynamix/DiskList.page @@ -14,80 +14,24 @@ Cond="$var['fsState']=='Started' && $var['shareDisk']!='no'" * all copies or substantial portions of the Software. */ ?> + -'.ucfirst($share['security']).''; -} -// Share size per disk -$preserve = $path==$prev; -$ssz2 = array(); -foreach (glob("state/*.ssz2", GLOB_NOSORT) as $entry) { - if ($preserve) { - $ssz2[basename($entry, ".ssz2")] = parse_ini_file($entry); - } else { - unlink($entry); - } -} -?> - - - - - - - - - - - - - $share_size): - if ($share_name!="total"): -?> - - - - - - - - - - - - - - - + - -
    There are no exportable disk shares
    - +

    > **Colored Status Indicator** the significance of the color indicator at the beginning of each line in *Disk Shares* is as follows: > diff --git a/plugins/dynamix/DiskSettings.page b/plugins/dynamix/DiskSettings.page index 6546e36b4..11222f5d3 100644 --- a/plugins/dynamix/DiskSettings.page +++ b/plugins/dynamix/DiskSettings.page @@ -14,7 +14,43 @@ Icon="disk-settings.png" * all copies or substantial portions of the Software. */ ?> -
    + + + + Enable auto start: : + +> *Warning disk utilization* sets the default warning threshold for all hard disks utilization. Exceeding this threshold will result in a warning notification. +> +> When the warning level is set equal or greater than the critical level, there will be only critical notifications (warnings are not existing). + +Default critical disk utilization level (%): +: + +> *Critical disk utilization* sets the default critical threshold for all hard disks utilization. Exceeding this threshold will result in an alert notification. + +Default warning disk temperature threshold (°): +: + +> *Warning disk temperature* sets the default warning threshold for all hard disks temperature. Exceeding this threshold will result in a warning notification. + +Default critical disk temperature threshold (°): +: + +> *Critical disk temperature* sets the default critical threshold for all hard disks temperature. Exceeding this threshold will result in an alert notification. +   :
    + +
    Global SMART Settings
    + +
    + + + + +Default SMART notification value: +: + +> SMART notifications are generated on either an increasing RAW value of the attribute, or a decreasing NORMALIZED value which reaches a predefined threshold set by the manufacturer. +> +> This section is used to set the global settings for all disks. It is possible to adjust settings for individual disks. + +Default SMART notification tolerance level: +: + +> A tolerance level may be given to prevent that small changes result in a notification. Setting a too high tolerance level may result in critical changes without a notification. +> +> This section is used to set the global settings for all disks. It is possible to adjust settings for individual disks. + +Default SMART controller type: +: + +> By default automatic controller selection is done by smartctl to read the SMART information. Certain controllers however need specific settings for smartctl to work. +> Use this setting to select your controller type and fill-in the specific disk index and device name for your situation. Use the manufacturer's documentation to find the relevant information. +> +> This section is used to set the global settings for all disks. It is possible to adjust settings for individual disks. + +Default SMART attribute notifications: +: Custom attributes (use comma to separate numbers) + + +  +: > + + +> The user can enable or disable notifications for the given SMART attributes. It is recommended to keep the default, which is ALL selected attributes, +> when certain attributes are not present on your hard disk or do not provide the correct information, these may be excluded. +> In addition custom SMART attributes can be entered to generate notifications. Be careful in this selection, +> it may cause an avalance of notifcations if inappropriate SMART attributes are chosen. +> +> This section is used to set the global settings for all disks. It is possible to adjust settings for individual disks. + + +: +
    diff --git a/plugins/dynamix/DisplaySettings.page b/plugins/dynamix/DisplaySettings.page index 6e05c7524..1cf0f586c 100644 --- a/plugins/dynamix/DisplaySettings.page +++ b/plugins/dynamix/DisplaySettings.page @@ -37,11 +37,9 @@ function restore() { $('select[name="banner"]').trigger('change'); filename = 'reset'; } - function forceReload() { window.onload = parent.location.reload(true); } - function upload(remove) { // gets invoked when the user clicks APPLY, at this point image will be saved or deleted if (remove || filename=='reset') { @@ -51,7 +49,20 @@ function upload(remove) { window.onload = forceReload(); } } - +function presetTime(form) { + var system = form.date.selectedIndex==0; + if (system) form.time.selectedIndex = 0; + form.time.disabled = system; +} +function presetBanner(form) { + if (form.banner.selectedIndex == 0) $('#custom').hide(); else $('#custom').show(); +} +function presetRefresh(form) { + for (var i=0,item; item=form.refresh.options[i]; i++) item.value *= -1; +} +function presetPassive(index) { + if (index==0) $('#passive').hide(); else $('#passive').show(); +} $(function() { // appending a time dummy will make the browser think/realize the image has changed $('#image').attr('src', $('#image').attr('src')+'?t='+new Date().getTime()); @@ -106,73 +117,15 @@ $(function() { presetTime(document.display_settings); presetBanner(document.display_settings); }); - -function prepareDisplay(form) { - if (!form.critical.value | !form.warning.value) { - swal({title:"Missing value",text:"An empty percentage value is not allowed!",type:"error"}); - return false; - } - if (form.warning.value>form.critical.value) { - swal({title:"Wrong value",text:"Warning percentage must be lower than Critical percentage!",type:"error"}); - return false; - } - if (!form.number.value) form.number.value='.,'; - if (form.unit.selectedIndex==1) { - form.hot.value = Math.round(5/9*(form.hot.value-32)); - form.max.value = Math.round(5/9*(form.max.value-32)); - } - return true; -} - -function presetTime(form) { - var system = form.date.selectedIndex==0; - if (system) form.time.selectedIndex = 0; - form.time.disabled = system; -} - -function presetBanner(form) { - if (form.banner.selectedIndex == 0) $('#custom').hide(); else $('#custom').show(); -} - -function presetTemp(form) { - var hot = $('#hot').html(); - var max = $('#max').html(); - if (form.unit.selectedIndex==0) { - form.hot.value = Math.round(5/9*(form.hot.value-32)); - form.max.value = Math.round(5/9*(form.max.value-32)); - $('#hot').html(hot.replace('F)','C)')); - $('#max').html(max.replace('F)','C)')); - } else { - form.hot.value = Math.round((9/5*form.hot.value)+32); - form.max.value = Math.round((9/5*form.max.value)+32); - $('#hot').html(hot.replace('C)','F)')); - $('#max').html(max.replace('C)','F)')); - } -} - -function presetRefresh(form) { - for (var i=0,item; item=form.refresh.options[i]; i++) item.value *= -1; -} - -function presetPassive(index) { - if (index==0) $('#passive').hide(); else $('#passive').show(); -} - -function checkTemp(form,what) { - if (form.hot.value>=form.max.value) { - var message = what ? 'Warning temperature must be lower than Critical temperature' : 'Critical temperature must be higher than Warning temperature'; - swal({title:"Incorrect value",text:message,type:"warning"}); - } -} > The display settings below determine how items are displayed on screen. Use these settings to tweak the visual effects to your likings. > > You can experiment with these settings as desired, they only affect visual properties. -
    - - + + + Date format: : - - + + + + + + Number scaling: @@ -221,6 +178,18 @@ Page view: +Placement of Users menu: +: + +Listing height: +: + Table view spacing: : -Warning disk utilization level (%): -: - -> *Warning disk utilization* sets the warning threshold for a hard disk utilization. Exceeding this threshold will result in a warning notification. -> -> When the warning level is set equal or greater than the critical level, there will be only critical notifications (warnings are not existing). - -Critical disk utilization level (%): -: - -> *Critical disk utilization* sets the critical threshold for a hard disk utilization. Exceeding this threshold will result in an alert notification. - Temperature unit: -: @@ -307,16 +264,6 @@ Temperature unit: > > Make sure any newly entered values represent the selected temperature unit. -Warning disk temperature threshold (°): -: - -> *Warning disk temperature* sets the warning threshold for a hard disk temperature. Exceeding this threshold will result in a warning notification. - -Critical disk temperature threshold (°): -: - -> *Critical disk temperature* sets the critical threshold for a hard disk temperature. Exceeding this threshold will result in an alert notification. - Page update frequency: : diff --git a/plugins/dynamix/OpenDevices.page b/plugins/dynamix/OpenDevices.page index 9c418ab6e..303eb8dd7 100644 --- a/plugins/dynamix/OpenDevices.page +++ b/plugins/dynamix/OpenDevices.page @@ -20,10 +20,10 @@ $tabX = '#tab'.($var['fsState']=='Stopped'||is_dir('/mnt/cache') ? '4' : '3'); ?> + "; } -echo "
    "; +echo $display['resize'] ? "