summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/xhr.js208
-rw-r--r--modules/luci-base/luasrc/dispatcher.lua2
-rw-r--r--modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab.lua14
-rw-r--r--themes/luci-theme-bootstrap/htdocs/luci-static/bootstrap/cascade.css23
4 files changed, 109 insertions, 138 deletions
diff --git a/modules/luci-base/htdocs/luci-static/resources/xhr.js b/modules/luci-base/htdocs/luci-static/resources/xhr.js
index 25a90e725..8292fcdb6 100644
--- a/modules/luci-base/htdocs/luci-static/resources/xhr.js
+++ b/modules/luci-base/htdocs/luci-static/resources/xhr.js
@@ -1,24 +1,65 @@
/*
* xhr.js - XMLHttpRequest helper class
- * (c) 2008-2010 Jo-Philipp Wich
+ * (c) 2008-2018 Jo-Philipp Wich <jo@mein.io>
*/
-XHR = function()
-{
- this.reinit = function()
- {
- if (window.XMLHttpRequest) {
- this._xmlHttp = new XMLHttpRequest();
+XHR.prototype = {
+ _encode: function(obj) {
+ obj = obj ? obj : { };
+ obj['_'] = Math.random();
+
+ if (typeof obj == 'object') {
+ var code = '';
+ var self = this;
+
+ for (var k in obj)
+ code += (code ? '&' : '') +
+ k + '=' + encodeURIComponent(obj[k]);
+
+ return code;
}
- else if (window.ActiveXObject) {
- this._xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
+
+ return obj;
+ },
+
+ _response: function(callback, ts) {
+ if (this._xmlHttp.readyState !== 4)
+ return;
+
+ var status = this._xmlHttp.status,
+ login = this._xmlHttp.getResponseHeader("X-LuCI-Login-Required"),
+ type = this._xmlHttp.getResponseHeader("Content-Type"),
+ json = null;
+
+ if (status === 403 && login === 'yes') {
+ XHR.halt();
+
+ showModal(_('Session expired'), [
+ E('div', { class: 'alert-message warning' },
+ _('A new login is required since the authentication session expired.')),
+ E('div', { class: 'right' },
+ E('div', {
+ class: 'btn primary',
+ click: function() {
+ var loc = window.location;
+ window.location = loc.protocol + '//' + loc.host + loc.pathname + loc.search;
+ }
+ }, _('To login…')))
+ ]);
}
- else {
- alert("xhr.js: XMLHttpRequest is not supported by this browser!");
+ else if (type && type.toLowerCase().match(/^application\/json\b/)) {
+ try {
+ json = JSON.parse(this._xmlHttp.responseText);
+ }
+ catch(e) {
+ json = null;
+ }
}
- }
- this.busy = function() {
+ callback(this._xmlHttp, json, Date.now() - ts);
+ },
+
+ busy: function() {
if (!this._xmlHttp)
return false;
@@ -32,20 +73,18 @@ XHR = function()
default:
return false;
}
- }
+ },
- this.abort = function() {
+ abort: function() {
if (this.busy())
this._xmlHttp.abort();
- }
+ },
- this.get = function(url,data,callback,timeout)
- {
- this.reinit();
+ get: function(url, data, callback, timeout) {
+ this._xmlHttp = new XMLHttpRequest();
- var ts = Date.now();
- var xhr = this._xmlHttp;
- var code = this._encode(data);
+ var xhr = this._xmlHttp,
+ code = this._encode(data);
url = location.protocol + '//' + location.host + url;
@@ -60,83 +99,51 @@ XHR = function()
if (!isNaN(timeout))
xhr.timeout = timeout;
- xhr.onreadystatechange = function()
- {
- if (xhr.readyState == 4) {
- var json = null;
- if (xhr.getResponseHeader("Content-Type") == "application/json") {
- try { json = JSON.parse(xhr.responseText); }
- catch(e) { json = null; }
- }
-
- callback(xhr, json, Date.now() - ts);
- }
- }
-
+ xhr.onreadystatechange = this._response.bind(this, callback, Date.now());
xhr.send(null);
- }
-
- this.post = function(url,data,callback,timeout)
- {
- this.reinit();
+ },
- var ts = Date.now();
- var xhr = this._xmlHttp;
- var code = this._encode(data);
+ post: function(url, data, callback, timeout) {
+ this._xmlHttp = new XMLHttpRequest();
- xhr.onreadystatechange = function()
- {
- if (xhr.readyState == 4) {
- var json = null;
- if (xhr.getResponseHeader("Content-Type") == "application/json") {
- try { json = JSON.parse(xhr.responseText); }
- catch(e) { json = null; }
- }
-
- callback(xhr, json, Date.now() - ts);
- }
- }
+ var xhr = this._xmlHttp,
+ code = this._encode(data);
xhr.open('POST', url, true);
if (!isNaN(timeout))
xhr.timeout = timeout;
+ xhr.onreadystatechange = this._response.bind(this, callback, Date.now());
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(code);
- }
+ },
- this.cancel = function()
- {
- this._xmlHttp.onreadystatechange = function(){};
+ cancel: function() {
+ this._xmlHttp.onreadystatechange = function() {};
this._xmlHttp.abort();
- }
+ },
- this.send_form = function(form,callback,extra_values)
- {
+ send_form: function(form, callback, extra_values) {
var code = '';
- for (var i = 0; i < form.elements.length; i++)
- {
+ for (var i = 0; i < form.elements.length; i++) {
var e = form.elements[i];
- if (e.options)
- {
+ if (e.options) {
code += (code ? '&' : '') +
form.elements[i].name + '=' + encodeURIComponent(
e.options[e.selectedIndex].value
);
}
- else if (e.length)
- {
+ else if (e.length) {
for (var j = 0; j < e.length; j++)
if (e[j].name) {
code += (code ? '&' : '') +
e[j].name + '=' + encodeURIComponent(e[j].value);
}
}
- else
- {
+ else {
code += (code ? '&' : '') +
e.name + '=' + encodeURIComponent(e.value);
}
@@ -147,46 +154,25 @@ XHR = function()
code += (code ? '&' : '') +
key + '=' + encodeURIComponent(extra_values[key]);
- return(
- (form.method == 'get')
- ? this.get(form.getAttribute('action'), code, callback)
- : this.post(form.getAttribute('action'), code, callback)
- );
- }
-
- this._encode = function(obj)
- {
- obj = obj ? obj : { };
- obj['_'] = Math.random();
-
- if (typeof obj == 'object')
- {
- var code = '';
- var self = this;
-
- for (var k in obj)
- code += (code ? '&' : '') +
- k + '=' + encodeURIComponent(obj[k]);
-
- return code;
- }
-
- return obj;
+ return (form.method == 'get'
+ ? this.get(form.getAttribute('action'), code, callback)
+ : this.post(form.getAttribute('action'), code, callback));
}
}
-XHR.get = function(url, data, callback)
-{
+XHR.get = function(url, data, callback) {
(new XHR()).get(url, data, callback);
}
-XHR.poll = function(interval, url, data, callback, post)
-{
+XHR.post = function(url, data, callback) {
+ (new XHR()).post(url, data, callback);
+}
+
+XHR.poll = function(interval, url, data, callback, post) {
if (isNaN(interval) || interval < 1)
interval = 5;
- if (!XHR._q)
- {
+ if (!XHR._q) {
XHR._t = 0;
XHR._q = [ ];
XHR._r = function() {
@@ -213,8 +199,7 @@ XHR.poll = function(interval, url, data, callback, post)
return e;
}
-XHR.stop = function(e)
-{
+XHR.stop = function(e) {
for (var i = 0; XHR._q && XHR._q[i]; i++) {
if (XHR._q[i] === e) {
e.xhr.cancel();
@@ -226,10 +211,8 @@ XHR.stop = function(e)
return false;
}
-XHR.halt = function()
-{
- if (XHR._i)
- {
+XHR.halt = function() {
+ if (XHR._i) {
/* show & set poll indicator */
try {
document.getElementById('xhr_poll_status').style.display = '';
@@ -242,10 +225,8 @@ XHR.halt = function()
}
}
-XHR.run = function()
-{
- if (XHR._r && !XHR._i)
- {
+XHR.run = function() {
+ if (XHR._r && !XHR._i) {
/* show & set poll indicator */
try {
document.getElementById('xhr_poll_status').style.display = '';
@@ -260,9 +241,10 @@ XHR.run = function()
}
}
-XHR.running = function()
-{
+XHR.running = function() {
return !!(XHR._r && XHR._i);
}
+function XHR() {}
+
document.addEventListener('DOMContentLoaded', XHR.run);
diff --git a/modules/luci-base/luasrc/dispatcher.lua b/modules/luci-base/luasrc/dispatcher.lua
index 1e610e748..c4066a259 100644
--- a/modules/luci-base/luasrc/dispatcher.lua
+++ b/modules/luci-base/luasrc/dispatcher.lua
@@ -417,6 +417,7 @@ function dispatch(request)
context.path = {}
http.status(403, "Forbidden")
+ http.header("X-LuCI-Login-Required", "yes")
tmpl.render(track.sysauth_template or "sysauth", {
duser = default_user,
fuser = user
@@ -433,6 +434,7 @@ function dispatch(request)
if not sid or not sdat then
http.status(403, "Forbidden")
+ http.header("X-LuCI-Login-Required", "yes")
return
end
diff --git a/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab.lua b/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab.lua
index 6f0921fdc..4a31146a0 100644
--- a/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab.lua
+++ b/modules/luci-mod-system/luasrc/model/cbi/admin_system/fstab.lua
@@ -117,14 +117,14 @@ function used.cfgvalue(self, section)
end
unmount = v:option(Button, "unmount", translate("Unmount"))
+function unmount.cfgvalue(self, section)
+ return non_system_mounts[section].umount
+end
+
unmount.render = function(self, section, scope)
- if non_system_mounts[section].umount then
- self.title = translate("Unmount")
- self.inputstyle = "remove"
- Button.render(self, section, scope)
- else
- luci.http.write("&#160;")
- end
+ self.title = translate("Unmount")
+ self.inputstyle = "remove"
+ Button.render(self, section, scope)
end
unmount.write = function(self, section)
diff --git a/themes/luci-theme-bootstrap/htdocs/luci-static/bootstrap/cascade.css b/themes/luci-theme-bootstrap/htdocs/luci-static/bootstrap/cascade.css
index 35ea81500..5f9d7e603 100644
--- a/themes/luci-theme-bootstrap/htdocs/luci-static/bootstrap/cascade.css
+++ b/themes/luci-theme-bootstrap/htdocs/luci-static/bootstrap/cascade.css
@@ -387,20 +387,20 @@ form .cbi-tab-descr {
}
form .clearfix,
-form .cbi-value {
+.cbi-value {
margin-bottom: 18px;
zoom: 1;
}
form .clearfix:before, form .clearfix:after,
-form .cbi-value:before, form .cbi-value:after {
+.cbi-value:before, .cbi-value:after {
display: table;
content: "";
zoom: 1;
}
form .clearfix:after,
-form .cbi-value:after {
+.cbi-value:after {
clear: both;
}
@@ -415,11 +415,11 @@ textarea {
}
form .input,
-form .cbi-value-field {
+.cbi-value-field {
margin-left: 200px;
}
-form .cbi-value label.cbi-value-title {
+.cbi-value label.cbi-value-title {
padding-top: 6px;
font-size: 13px;
line-height: 18px;
@@ -1770,19 +1770,6 @@ a.label:hover {
/* LuCI specific items */
.hidden { display: none }
-#memtotal > div,
-#memfree > div,
-#memcache > div,
-#membuff > div,
-#conns > div {
- border: 1px solid #ccc;
- border-radius: 3px 3px 3px 3px;
- color: #808080;
- display: inline-block;
- font-size: 13px;
- line-height: 18px;
-}
-
#xhr_poll_status {
cursor: pointer;
}