Merge pull request #2390 from freifunk-gluon/v2021.1.x-backports
Backports for v2021.1.x
This commit is contained in:
commit
e51836ecf1
4
.github/workflows/lint.yml
vendored
4
.github/workflows/lint.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: sudo apt install lua-check
|
run: sudo apt-get -y update && sudo apt-get -y install lua-check
|
||||||
- name: Install example site
|
- name: Install example site
|
||||||
run: ln -s ./docs/site-example ./site
|
run: ln -s ./docs/site-example ./site
|
||||||
- name: Lint Lua code
|
- name: Lint Lua code
|
||||||
@ -22,7 +22,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: sudo apt install shellcheck
|
run: sudo apt-get -y update && sudo apt-get -y install shellcheck
|
||||||
- name: Install example site
|
- name: Install example site
|
||||||
run: ln -s ./docs/site-example ./site
|
run: ln -s ./docs/site-example ./site
|
||||||
- name: Lint shell code
|
- name: Lint shell code
|
||||||
|
5
Makefile
5
Makefile
@ -19,8 +19,9 @@ escape = '$(subst ','\'',$(1))'
|
|||||||
GLUON_SITEDIR ?= site
|
GLUON_SITEDIR ?= site
|
||||||
$(eval $(call mkabspath,GLUON_SITEDIR))
|
$(eval $(call mkabspath,GLUON_SITEDIR))
|
||||||
|
|
||||||
$(GLUON_SITEDIR)/site.mk:
|
ifeq ($(realpath $(GLUON_SITEDIR)/site.mk),)
|
||||||
$(error No site configuration was found. Please check out a site configuration to $(GLUON_SITEDIR))
|
$(error No site configuration was found. Please check out a site configuration to $(GLUON_SITEDIR))
|
||||||
|
endif
|
||||||
|
|
||||||
include $(GLUON_SITEDIR)/site.mk
|
include $(GLUON_SITEDIR)/site.mk
|
||||||
|
|
||||||
|
@ -478,7 +478,7 @@ config_mode \: optional
|
|||||||
|
|
||||||
*openlayers_url* allows to override the base URL of the
|
*openlayers_url* allows to override the base URL of the
|
||||||
*build/ol.js* and *css/ol.css* files (the default is
|
*build/ol.js* and *css/ol.css* files (the default is
|
||||||
``https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.2.0``).
|
``https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@35ffe7626ce16c372143f3c903950750075e7068/en/v5.3.0``).
|
||||||
It is also possible to replace the default tile layer (which is OpenStreetMap)
|
It is also possible to replace the default tile layer (which is OpenStreetMap)
|
||||||
with a custom one using the *tile_layer* section. Only XYZ layers are supported
|
with a custom one using the *tile_layer* section. Only XYZ layers are supported
|
||||||
at this point.
|
at this point.
|
||||||
|
@ -22,7 +22,7 @@ function f:write()
|
|||||||
uci:set("gluon-setup-mode", uci:get_first("gluon-setup-mode", "setup_mode"), "configured", true)
|
uci:set("gluon-setup-mode", uci:get_first("gluon-setup-mode", "setup_mode"), "configured", true)
|
||||||
uci:save("gluon-setup-mode")
|
uci:save("gluon-setup-mode")
|
||||||
|
|
||||||
os.execute('gluon-reconfigure')
|
os.execute('exec gluon-reconfigure >/dev/null')
|
||||||
|
|
||||||
f.template = "wizard/reboot"
|
f.template = "wizard/reboot"
|
||||||
f.package = "gluon-config-mode-core"
|
f.package = "gluon-config-mode-core"
|
||||||
|
@ -69,8 +69,23 @@ void tv_subtract (struct timeval *r, const struct timeval *a, const struct timev
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t recvtimeout(int socket, void *buffer, size_t length, int flags, const struct timeval *timeout) {
|
void resize_recvbuffer(char **recvbuffer, size_t *recvbuffer_len, size_t recvlen)
|
||||||
|
{
|
||||||
|
free(*recvbuffer);
|
||||||
|
*recvbuffer = malloc(recvlen);
|
||||||
|
|
||||||
|
if (!(*recvbuffer)) {
|
||||||
|
perror("Could not resize recvbuffer");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
*recvbuffer_len = recvlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t recvtimeout(int socket, char **recvbuffer, size_t *recvbuffer_len,
|
||||||
|
const struct timeval *timeout) {
|
||||||
struct timeval now, timeout_left;
|
struct timeval now, timeout_left;
|
||||||
|
ssize_t recvlen;
|
||||||
|
|
||||||
getclock(&now);
|
getclock(&now);
|
||||||
tv_subtract(&timeout_left, timeout, &now);
|
tv_subtract(&timeout_left, timeout, &now);
|
||||||
@ -79,18 +94,28 @@ ssize_t recvtimeout(int socket, void *buffer, size_t length, int flags, const st
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &timeout_left, sizeof(timeout_left));
|
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &timeout_left, sizeof(timeout_left));
|
||||||
return recv(socket, buffer, length, flags);
|
|
||||||
|
recvlen = recv(socket, NULL, 0, MSG_PEEK | MSG_TRUNC);
|
||||||
|
if (recvlen < 0)
|
||||||
|
return recvlen;
|
||||||
|
|
||||||
|
if (recvlen > *recvbuffer_len)
|
||||||
|
resize_recvbuffer(recvbuffer, recvbuffer_len, recvlen);
|
||||||
|
|
||||||
|
return recv(socket, *recvbuffer, *recvbuffer_len, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int request(const int sock, const struct sockaddr_in6 *client_addr, const char *request, const char *sse, double timeout, unsigned int max_count) {
|
int request(const int sock, char **recvbuffer, size_t *recvbuffer_len,
|
||||||
|
const struct sockaddr_in6 *client_addr, const char *request,
|
||||||
|
const char *sse, double timeout, unsigned int max_count) {
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
char buffer[8192];
|
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
|
|
||||||
ret = sendto(sock, request, strlen(request), 0, (struct sockaddr *)client_addr, sizeof(struct sockaddr_in6));
|
ret = sendto(sock, request, strlen(request), 0, (struct sockaddr *)client_addr, sizeof(struct sockaddr_in6));
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
perror("Error in sendto()");
|
perror("Error in sendto()");
|
||||||
|
free(*recvbuffer);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +130,7 @@ int request(const int sock, const struct sockaddr_in6 *client_addr, const char *
|
|||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = recvtimeout(sock, buffer, sizeof(buffer), 0, &tv_timeout);
|
ret = recvtimeout(sock, recvbuffer, recvbuffer_len, &tv_timeout);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
break;
|
break;
|
||||||
@ -116,7 +141,7 @@ int request(const int sock, const struct sockaddr_in6 *client_addr, const char *
|
|||||||
fputs("data: ", stdout);
|
fputs("data: ", stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
fwrite(buffer, sizeof(char), ret, stdout);
|
fwrite(*recvbuffer, sizeof(char), ret, stdout);
|
||||||
|
|
||||||
if (sse)
|
if (sse)
|
||||||
fputs("\n\n", stdout);
|
fputs("\n\n", stdout);
|
||||||
@ -137,6 +162,8 @@ int main(int argc, char **argv) {
|
|||||||
int sock;
|
int sock;
|
||||||
struct sockaddr_in6 client_addr = {};
|
struct sockaddr_in6 client_addr = {};
|
||||||
char *request_string = NULL;
|
char *request_string = NULL;
|
||||||
|
char *recvbuffer = NULL;
|
||||||
|
size_t recvbuffer_len = 0;
|
||||||
|
|
||||||
sock = socket(PF_INET6, SOCK_DGRAM, 0);
|
sock = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||||
|
|
||||||
@ -243,11 +270,13 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = request(sock, &client_addr, request_string, sse, timeout, max_count);
|
ret = request(sock, &recvbuffer, &recvbuffer_len, &client_addr,
|
||||||
|
request_string, sse, timeout, max_count);
|
||||||
} while(loop);
|
} while(loop);
|
||||||
|
|
||||||
if (sse)
|
if (sse)
|
||||||
fputs("event: eot\ndata: null\n\n", stdout);
|
fputs("event: eot\ndata: null\n\n", stdout);
|
||||||
|
|
||||||
|
free(recvbuffer);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
<%-
|
<%-
|
||||||
|
local iwinfo = require 'iwinfo'
|
||||||
local ubus = require 'ubus'
|
local ubus = require 'ubus'
|
||||||
local unistd = require 'posix.unistd'
|
local unistd = require 'posix.unistd'
|
||||||
local util = require 'gluon.util'
|
local util = require 'gluon.util'
|
||||||
|
local wireless = require 'gluon.wireless'
|
||||||
|
|
||||||
|
local uci = require('simple-uci').cursor()
|
||||||
|
|
||||||
local translations = {}
|
local translations = {}
|
||||||
local site_i18n = i18n 'gluon-site'
|
local site_i18n = i18n 'gluon-site'
|
||||||
@ -29,17 +33,31 @@
|
|||||||
|
|
||||||
local mesh = get_mesh()
|
local mesh = get_mesh()
|
||||||
|
|
||||||
local function get_interfaces()
|
local function get_interfaces(uconn)
|
||||||
local uconn = ubus.connect()
|
|
||||||
if not uconn then
|
|
||||||
error('failed to connect to ubus')
|
|
||||||
end
|
|
||||||
local interfaces = util.get_mesh_devices(uconn)
|
local interfaces = util.get_mesh_devices(uconn)
|
||||||
ubus.close(uconn)
|
|
||||||
table.sort(interfaces)
|
table.sort(interfaces)
|
||||||
return interfaces
|
return interfaces
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function get_radios()
|
||||||
|
local ret = {}
|
||||||
|
|
||||||
|
wireless.foreach_radio(uci, function(radio)
|
||||||
|
local channel = iwinfo.nl80211.channel(wireless.find_phy(radio))
|
||||||
|
if channel then
|
||||||
|
table.insert(ret, {
|
||||||
|
name = radio['.name'],
|
||||||
|
channel = channel,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
table.sort(ret, function(a, b)
|
||||||
|
return a.name < b.name
|
||||||
|
end)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
local function is_wireless(iface)
|
local function is_wireless(iface)
|
||||||
while true do
|
while true do
|
||||||
local pattern = '/sys/class/net/' .. iface .. '/lower_*'
|
local pattern = '/sys/class/net/' .. iface .. '/lower_*'
|
||||||
@ -52,7 +70,16 @@
|
|||||||
return unistd.access('/sys/class/net/' .. iface .. '/wireless') ~= nil
|
return unistd.access('/sys/class/net/' .. iface .. '/wireless') ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local interfaces = get_interfaces()
|
local uconn = ubus.connect()
|
||||||
|
if not uconn then
|
||||||
|
error('failed to connect to ubus')
|
||||||
|
end
|
||||||
|
|
||||||
|
local interfaces = get_interfaces(uconn)
|
||||||
|
|
||||||
|
ubus.close(uconn)
|
||||||
|
|
||||||
|
local radios = get_radios()
|
||||||
|
|
||||||
local function sorted(t)
|
local function sorted(t)
|
||||||
t = {unpack(t)}
|
t = {unpack(t)}
|
||||||
@ -66,12 +93,17 @@
|
|||||||
|
|
||||||
local function formatBits(bits)
|
local function formatBits(bits)
|
||||||
local units = {[0]='', 'k', 'M', 'G'}
|
local units = {[0]='', 'k', 'M', 'G'}
|
||||||
|
local unit = 0
|
||||||
|
|
||||||
local pow = math.floor(math.log(math.max(math.abs(bits), 1)) / math.log(1000))
|
for i = 1, #units do
|
||||||
local known_pow = math.min(pow, #units)
|
if math.abs(bits) < 1000 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
unit = i
|
||||||
|
bits = bits / 1000
|
||||||
|
end
|
||||||
|
|
||||||
local significand = bits/(1000^known_pow)
|
return string.format('%g %sbit', bits, units[unit])
|
||||||
return string.format('%g %sbit', significand, units[known_pow])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function statistics(key, format)
|
local function statistics(key, format)
|
||||||
@ -135,11 +167,11 @@
|
|||||||
<% if nodeinfo.network.mesh_vpn.bandwidth_limit.enabled then -%>
|
<% if nodeinfo.network.mesh_vpn.bandwidth_limit.enabled then -%>
|
||||||
<dt><%:Bandwidth limit%></dt>
|
<dt><%:Bandwidth limit%></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<% if nodeinfo.network.mesh_vpn.bandwidth_limit.egress then -%>
|
|
||||||
▲ <%| formatBits(nodeinfo.network.mesh_vpn.bandwidth_limit.egress*1000) %>/s <%:upstream%><br />
|
|
||||||
<%- end %>
|
|
||||||
<% if nodeinfo.network.mesh_vpn.bandwidth_limit.ingress then -%>
|
<% if nodeinfo.network.mesh_vpn.bandwidth_limit.ingress then -%>
|
||||||
▼ <%| formatBits(nodeinfo.network.mesh_vpn.bandwidth_limit.ingress*1000) %>/s <%:downstream%>
|
▼ <%| formatBits(nodeinfo.network.mesh_vpn.bandwidth_limit.ingress*1000) %>/s <%:downstream%><br />
|
||||||
|
<%- end %>
|
||||||
|
<% if nodeinfo.network.mesh_vpn.bandwidth_limit.egress then -%>
|
||||||
|
▲ <%| formatBits(nodeinfo.network.mesh_vpn.bandwidth_limit.egress*1000) %>/s <%:upstream%>
|
||||||
<%- end %>
|
<%- end %>
|
||||||
</dd>
|
</dd>
|
||||||
<%- end %>
|
<%- end %>
|
||||||
@ -190,11 +222,17 @@
|
|||||||
<tr><th><%:Wireless 2.4 GHz%></th><td><%= statistics('clients/wifi24') %></td></tr>
|
<tr><th><%:Wireless 2.4 GHz%></th><td><%= statistics('clients/wifi24') %></td></tr>
|
||||||
<tr><th><%:Wireless 5 GHz%></th><td><%= statistics('clients/wifi5') %></td></tr>
|
<tr><th><%:Wireless 5 GHz%></th><td><%= statistics('clients/wifi5') %></td></tr>
|
||||||
</table>
|
</table>
|
||||||
<div id="radios" style="display: none">
|
<% if radios[1] then -%>
|
||||||
<h3><%:Radios%></h3>
|
<h3><%:Radios%></h3>
|
||||||
<table id="radio-devices">
|
<table>
|
||||||
|
<% for _, radio in ipairs(radios) do -%>
|
||||||
|
<tr>
|
||||||
|
<th><%| radio.name %></th>
|
||||||
|
<td><%| translatef('Channel %u', radio.channel) %></td>
|
||||||
|
</tr>
|
||||||
|
<%- end %>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
<%- end %>
|
||||||
|
|
||||||
<h3><%:Traffic%></h3>
|
<h3><%:Traffic%></h3>
|
||||||
<table>
|
<table>
|
||||||
|
File diff suppressed because one or more lines are too long
@ -31,8 +31,8 @@ msgstr "Automatische Updates"
|
|||||||
msgid "Bandwidth limit"
|
msgid "Bandwidth limit"
|
||||||
msgstr "Bandbreitenlimit"
|
msgstr "Bandbreitenlimit"
|
||||||
|
|
||||||
msgid "Channel"
|
msgid "Channel %u"
|
||||||
msgstr "Kanal"
|
msgstr "Kanal %u"
|
||||||
|
|
||||||
msgid "Clients"
|
msgid "Clients"
|
||||||
msgstr "Clients"
|
msgstr "Clients"
|
||||||
|
@ -22,7 +22,7 @@ msgstr ""
|
|||||||
msgid "Bandwidth limit"
|
msgid "Bandwidth limit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Channel"
|
msgid "Channel %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clients"
|
msgid "Clients"
|
||||||
|
@ -121,7 +121,15 @@
|
|||||||
var neigh = iface.lookup_neigh(addr);
|
var neigh = iface.lookup_neigh(addr);
|
||||||
if (!neigh)
|
if (!neigh)
|
||||||
continue;
|
continue;
|
||||||
return 'via ' + neigh.get_hostname() + ' (' + i + ')';
|
|
||||||
|
var span = document.createElement('span');
|
||||||
|
span.appendChild(document.createTextNode('via '));
|
||||||
|
var a = document.createElement('a');
|
||||||
|
a.href = 'http://[' + neigh.get_addr() + ']/';
|
||||||
|
a.textContent = neigh.get_hostname();
|
||||||
|
span.appendChild(a);
|
||||||
|
span.appendChild(document.createTextNode(' (' + i + ')'));
|
||||||
|
return span;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'via ' + addr + ' (unknown iface)';
|
return 'via ' + addr + ' (unknown iface)';
|
||||||
@ -208,50 +216,6 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function update_radios(wireless) {
|
|
||||||
function channel(frequency) {
|
|
||||||
if (frequency===2484)
|
|
||||||
return 14
|
|
||||||
|
|
||||||
if (2412<=frequency && frequency<=2472)
|
|
||||||
return (frequency-2407)/5
|
|
||||||
|
|
||||||
if (5160<=frequency && frequency<=5885)
|
|
||||||
return (frequency-5000)/5
|
|
||||||
|
|
||||||
return 'unknown'
|
|
||||||
}
|
|
||||||
|
|
||||||
var div = document.getElementById('radios');
|
|
||||||
if (!wireless) {
|
|
||||||
div.style.display = 'none';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
div.style.display = '';
|
|
||||||
|
|
||||||
var table = document.getElementById('radio-devices');
|
|
||||||
while (table.lastChild)
|
|
||||||
table.removeChild(table.lastChild);
|
|
||||||
|
|
||||||
wireless.sort(function (a, b) {
|
|
||||||
return a.phy - b.phy;
|
|
||||||
});
|
|
||||||
|
|
||||||
wireless.forEach(function (radio) {
|
|
||||||
var tr = document.createElement('tr');
|
|
||||||
|
|
||||||
var th = document.createElement('th');
|
|
||||||
th.textContent = "phy" + radio.phy;
|
|
||||||
tr.appendChild(th);
|
|
||||||
|
|
||||||
var td = document.createElement('td');
|
|
||||||
td.innerHTML = radio.frequency + " MHz<br />Channel " + channel(radio.frequency);
|
|
||||||
tr.appendChild(td);
|
|
||||||
|
|
||||||
table.appendChild(tr);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var statisticsElems = document.querySelectorAll('[data-statistics]');
|
var statisticsElems = document.querySelectorAll('[data-statistics]');
|
||||||
|
|
||||||
add_event_source('/cgi-bin/dyn/statistics', function(data, dataPrev) {
|
add_event_source('/cgi-bin/dyn/statistics', function(data, dataPrev) {
|
||||||
@ -264,9 +228,16 @@
|
|||||||
var valuePrev = resolve_key(dataPrev, stat);
|
var valuePrev = resolve_key(dataPrev, stat);
|
||||||
var value = resolve_key(data, stat);
|
var value = resolve_key(data, stat);
|
||||||
try {
|
try {
|
||||||
var text = formats[format](value, valuePrev, diff);
|
var format_result = formats[format](value, valuePrev, diff);
|
||||||
if (text !== undefined)
|
switch (typeof format_result) {
|
||||||
elem.textContent = text;
|
case "object":
|
||||||
|
if (elem.lastChild)
|
||||||
|
elem.removeChild(elem.lastChild);
|
||||||
|
elem.appendChild(format_result);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
elem.textContent = format_result;
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
@ -277,11 +248,6 @@
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
update_radios(data.wireless);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
function haversine(lat1, lon1, lat2, lon2) {
|
function haversine(lat1, lon1, lat2, lon2) {
|
||||||
@ -319,7 +285,7 @@
|
|||||||
'resize': function(w, h) {
|
'resize': function(w, h) {
|
||||||
var lastImage;
|
var lastImage;
|
||||||
try {
|
try {
|
||||||
ctx.getImageData(0, 0, w, h);
|
lastImage = ctx.getImageData(0, 0, w, h);
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
canvas.width = w;
|
canvas.width = w;
|
||||||
canvas.height = h;
|
canvas.height = h;
|
||||||
@ -492,6 +458,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var hostname = document.createElement("span");
|
var hostname = document.createElement("span");
|
||||||
|
var addr;
|
||||||
hostname.textContent = addr;
|
hostname.textContent = addr;
|
||||||
tdHostname.appendChild(hostname);
|
tdHostname.appendChild(hostname);
|
||||||
|
|
||||||
@ -552,13 +519,13 @@
|
|||||||
el.classList.add("highlight");
|
el.classList.add("highlight");
|
||||||
if (signal)
|
if (signal)
|
||||||
signal.highlight = true;
|
signal.highlight = true;
|
||||||
}
|
};
|
||||||
|
|
||||||
el.onmouseleave = function () {
|
el.onmouseleave = function () {
|
||||||
el.classList.remove("highlight")
|
el.classList.remove("highlight");
|
||||||
if (signal)
|
if (signal)
|
||||||
signal.highlight = false;
|
signal.highlight = false;
|
||||||
}
|
};
|
||||||
|
|
||||||
var timeout;
|
var timeout;
|
||||||
|
|
||||||
@ -586,7 +553,8 @@
|
|||||||
var n = parts.length;
|
var n = parts.length;
|
||||||
var groups = [];
|
var groups = [];
|
||||||
|
|
||||||
parts.forEach(function(part, i) {
|
for (var i = 0; i < parts.length; i++) {
|
||||||
|
var part = parts[i];
|
||||||
if (part === '') {
|
if (part === '') {
|
||||||
while (n++ <= 8)
|
while (n++ <= 8)
|
||||||
groups.push(0);
|
groups.push(0);
|
||||||
@ -596,7 +564,7 @@
|
|||||||
|
|
||||||
groups.push(parseInt(part, 16));
|
groups.push(parseInt(part, 16));
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
return groups;
|
return groups;
|
||||||
}
|
}
|
||||||
@ -664,8 +632,11 @@
|
|||||||
'get_hostname': function() {
|
'get_hostname': function() {
|
||||||
return hostname.textContent;
|
return hostname.textContent;
|
||||||
},
|
},
|
||||||
|
'get_addr': function() {
|
||||||
|
return addr;
|
||||||
|
},
|
||||||
'update_nodeinfo': function(nodeinfo) {
|
'update_nodeinfo': function(nodeinfo) {
|
||||||
var addr = choose_address(nodeinfo.network.addresses);
|
addr = choose_address(nodeinfo.network.addresses);
|
||||||
if (addr) {
|
if (addr) {
|
||||||
if (hostname.nodeName.toLowerCase() === 'span') {
|
if (hostname.nodeName.toLowerCase() === 'span') {
|
||||||
var oldHostname = hostname;
|
var oldHostname = hostname;
|
||||||
|
@ -61,7 +61,7 @@ local function match(a, b, n)
|
|||||||
end
|
end
|
||||||
|
|
||||||
entry({}, call(function(http, renderer)
|
entry({}, call(function(http, renderer)
|
||||||
local nodeinfo = json.parse(util.exec('exec gluon-neighbour-info -d ::1 -p 1001 -t 1 -c 1 -r nodeinfo'))
|
local nodeinfo = json.parse(util.exec('exec gluon-neighbour-info -d ::1 -p 1001 -t 3 -c 1 -r nodeinfo'))
|
||||||
|
|
||||||
local node_ip = parse_ip(http:getenv('SERVER_ADDR'))
|
local node_ip = parse_ip(http:getenv('SERVER_ADDR'))
|
||||||
if node_ip and (
|
if node_ip and (
|
||||||
|
@ -44,7 +44,6 @@ $Id$
|
|||||||
|
|
||||||
<div class="gluon-page-actions">
|
<div class="gluon-page-actions">
|
||||||
<input type="hidden" name="step" value="2" />
|
<input type="hidden" name="step" value="2" />
|
||||||
<input type="hidden" name="token" value="<%=token%>" />
|
|
||||||
<input class="gluon-button gluon-button-submit" type="submit" value="<%:Upload image%>" />
|
<input class="gluon-button gluon-button-submit" type="submit" value="<%:Upload image%>" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -49,13 +49,11 @@ You may obtain a copy of the License at
|
|||||||
<form method="post" enctype="multipart/form-data" action="<%|url(request)%>" style="display:inline">
|
<form method="post" enctype="multipart/form-data" action="<%|url(request)%>" style="display:inline">
|
||||||
<input type="hidden" name="step" value="3" />
|
<input type="hidden" name="step" value="3" />
|
||||||
<input type="hidden" name="keepcfg" value="<%=keepconfig and "1" or "0"%>" />
|
<input type="hidden" name="keepcfg" value="<%=keepconfig and "1" or "0"%>" />
|
||||||
<input type="hidden" name="token" value="<%=token%>" />
|
|
||||||
<input class="gluon-button gluon-button-submit" type="submit" value="<%:Continue%>" />
|
<input class="gluon-button gluon-button-submit" type="submit" value="<%:Continue%>" />
|
||||||
</form>
|
</form>
|
||||||
<form method="post" enctype="multipart/form-data" action="<%|url(request)%>" style="display:inline">
|
<form method="post" enctype="multipart/form-data" action="<%|url(request)%>" style="display:inline">
|
||||||
<input type="hidden" name="step" value="1" />
|
<input type="hidden" name="step" value="1" />
|
||||||
<input type="hidden" name="keepcfg" value="<%=keepconfig and "1" or "0"%>" />
|
<input type="hidden" name="keepcfg" value="<%=keepconfig and "1" or "0"%>" />
|
||||||
<input type="hidden" name="token" value="<%=token%>" />
|
|
||||||
<input class="gluon-button gluon-button-reset" type="submit" value="<%:Cancel%>" />
|
<input class="gluon-button gluon-button-reset" type="submit" value="<%:Cancel%>" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
<form method="post" enctype="multipart/form-data" action="<%|url(request)%>" data-update="reset">
|
<form method="post" enctype="multipart/form-data" action="<%|url(request)%>" data-update="reset">
|
||||||
<input type="hidden" name="token" value="<%=token%>" />
|
|
||||||
<input type="hidden" name="<%=id%>" value="1" />
|
<input type="hidden" name="<%=id%>" value="1" />
|
||||||
|
|
||||||
<div class="gluon-form" id="form-<%=id%>">
|
<div class="gluon-form" id="form-<%=id%>">
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<div id="<%=id%>" class="gluon-osm-map" style="display: none"></div>
|
<div id="<%=id%>" class="gluon-osm-map" style="display: none"></div>
|
||||||
<script type="text/javascript" src="/static/gluon-web-osm.js"></script>
|
<script type="text/javascript" src="/static/gluon-web-osm.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
//<![CDATA[
|
||||||
(function() {
|
(function() {
|
||||||
var elMap = document.getElementById(<%=json(id)%>);
|
var elMap = document.getElementById(<%=json(id)%>);
|
||||||
var wrapper = elMap.parentNode;
|
var wrapper = elMap.parentNode;
|
||||||
@ -41,4 +42,5 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
//]]>
|
||||||
</script>
|
</script>
|
||||||
|
@ -4,7 +4,8 @@ local util = require "gluon.web.util"
|
|||||||
local class = util.class
|
local class = util.class
|
||||||
|
|
||||||
|
|
||||||
local DEFAULT_URL = 'https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.2.0'
|
local DEFAULT_URL =
|
||||||
|
'https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@35ffe7626ce16c372143f3c903950750075e7068/en/v5.3.0'
|
||||||
|
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
@ -184,9 +184,15 @@ local function dispatch(config, http, request)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
http:parse_input(node.filehandler)
|
local ok, err = pcall(http.parse_input, http, node.filehandler)
|
||||||
|
if not ok then
|
||||||
|
http:status(400, "Bad request")
|
||||||
|
http:prepare_content("text/plain")
|
||||||
|
http:write(err .. "\r\n")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local ok, err = pcall(node.target)
|
ok, err = pcall(node.target)
|
||||||
if not ok then
|
if not ok then
|
||||||
http:status(500, "Internal Server Error")
|
http:status(500, "Internal Server Error")
|
||||||
renderer.render_layout("error/500", {
|
renderer.render_layout("error/500", {
|
||||||
@ -208,6 +214,6 @@ return function(config, http)
|
|||||||
if not ok then
|
if not ok then
|
||||||
http:status(500, "Internal Server Error")
|
http:status(500, "Internal Server Error")
|
||||||
http:prepare_content("text/plain")
|
http:prepare_content("text/plain")
|
||||||
http:write(err)
|
http:write(err .. "\r\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -108,16 +108,11 @@ end
|
|||||||
-- o String value containing a chunk of the file data
|
-- o String value containing a chunk of the file data
|
||||||
-- o Boolean which indicates whether the current chunk is the last one (eof)
|
-- o Boolean which indicates whether the current chunk is the last one (eof)
|
||||||
local function mimedecode_message_body(src, msg, filecb)
|
local function mimedecode_message_body(src, msg, filecb)
|
||||||
|
local mime_boundary = (msg.env.CONTENT_TYPE or ''):match("^multipart/form%-data; boundary=(.+)$")
|
||||||
if msg and msg.env.CONTENT_TYPE then
|
if not mime_boundary then
|
||||||
msg.mime_boundary = msg.env.CONTENT_TYPE:match("^multipart/form%-data; boundary=(.+)$")
|
error("Invalid Content-Type found")
|
||||||
end
|
end
|
||||||
|
|
||||||
if not msg.mime_boundary then
|
|
||||||
return nil, "Invalid Content-Type found"
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local tlen = 0
|
local tlen = 0
|
||||||
local inhdr = false
|
local inhdr = false
|
||||||
local field = nil
|
local field = nil
|
||||||
@ -188,10 +183,10 @@ local function mimedecode_message_body(src, msg, filecb)
|
|||||||
local spos, epos, found
|
local spos, epos, found
|
||||||
|
|
||||||
repeat
|
repeat
|
||||||
spos, epos = data:find("\r\n--" .. msg.mime_boundary .. "\r\n", 1, true)
|
spos, epos = data:find("\r\n--" .. mime_boundary .. "\r\n", 1, true)
|
||||||
|
|
||||||
if not spos then
|
if not spos then
|
||||||
spos, epos = data:find("\r\n--" .. msg.mime_boundary .. "--\r\n", 1, true)
|
spos, epos = data:find("\r\n--" .. mime_boundary .. "--\r\n", 1, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -250,20 +245,61 @@ local function mimedecode_message_body(src, msg, filecb)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return pump(src, snk)
|
assert(pump(src, snk))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function check_post_origin(msg)
|
||||||
|
local default_port = '80'
|
||||||
|
local request_scheme = 'http'
|
||||||
|
if msg.env.HTTPS then
|
||||||
|
default_port = '443'
|
||||||
|
request_scheme = 'https'
|
||||||
|
end
|
||||||
|
|
||||||
|
local request_host = msg.env.HTTP_HOST
|
||||||
|
if not request_host then
|
||||||
|
error('POST request without Host header')
|
||||||
|
end
|
||||||
|
if not request_host:match(':[0-9]+$') then
|
||||||
|
request_host = request_host .. ':' .. default_port
|
||||||
|
end
|
||||||
|
|
||||||
|
local origin = msg.env.HTTP_ORIGIN
|
||||||
|
if not origin then
|
||||||
|
error('POST request without Origin header')
|
||||||
|
end
|
||||||
|
local origin_scheme, origin_host = origin:match('^([^:]*)://(.*)$')
|
||||||
|
if not origin_host then
|
||||||
|
error('POST request with invalid Origin header')
|
||||||
|
end
|
||||||
|
if not origin_host:match(':[0-9]+$') then
|
||||||
|
local origin_port
|
||||||
|
if origin_scheme == 'http' then
|
||||||
|
origin_port = '80'
|
||||||
|
elseif origin_scheme == 'https' then
|
||||||
|
origin_port = '443'
|
||||||
|
else
|
||||||
|
error('POST request with invalid Origin header')
|
||||||
|
end
|
||||||
|
origin_host = origin_host .. ':' .. origin_port
|
||||||
|
end
|
||||||
|
|
||||||
|
if request_scheme ~= origin_scheme or request_host ~= origin_host then
|
||||||
|
error('Invalid cross-origin POST')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- This function will examine the Content-Type within the given message object
|
-- This function will examine the Content-Type within the given message object
|
||||||
-- to select the appropriate content decoder.
|
-- to select the appropriate content decoder.
|
||||||
-- Currently only the multipart/form-data mime type is supported.
|
-- Currently only the multipart/form-data mime type is supported.
|
||||||
function M.parse_message_body(src, msg, filecb)
|
function M.parse_message_body(src, msg, filecb)
|
||||||
if not (msg.env.REQUEST_METHOD == "POST" and msg.env.CONTENT_TYPE) then
|
if msg.env.REQUEST_METHOD ~= "POST" then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if msg.env.CONTENT_TYPE:match("^multipart/form%-data") then
|
check_post_origin(msg)
|
||||||
return mimedecode_message_body(src, msg, filecb)
|
|
||||||
end
|
mimedecode_message_body(src, msg, filecb)
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
From: Martin Weinelt <martin@darmstadt.freifunk.net>
|
||||||
|
Date: Tue, 8 Feb 2022 21:09:20 +0100
|
||||||
|
Subject: perl: don't build in parallel and bump release
|
||||||
|
|
||||||
|
Parallel builds cause spurious build failures with high core counts.
|
||||||
|
|
||||||
|
https://github.com/openwrt/packages/issues/8238
|
||||||
|
https://github.com/openwrt/packages/pull/17274
|
||||||
|
|
||||||
|
diff --git a/lang/perl/Makefile b/lang/perl/Makefile
|
||||||
|
index 84d256d2d8c682f18670a4cbae0a48e3333fb222..c2e5cf8e703af675dd296704597934aa9b5f7446 100644
|
||||||
|
--- a/lang/perl/Makefile
|
||||||
|
+++ b/lang/perl/Makefile
|
||||||
|
@@ -34,8 +34,8 @@ PKG_BUILD_DIR:=$(BUILD_DIR)/perl/$(PKG_NAME)-$(PKG_VERSION)
|
||||||
|
HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/perl/$(PKG_NAME)-$(PKG_VERSION)
|
||||||
|
PKG_INSTALL:=1
|
||||||
|
PKG_BUILD_DEPENDS:=perl/host
|
||||||
|
-PKG_BUILD_PARALLEL:=1
|
||||||
|
-HOST_BUILD_PARALLEL:=1
|
||||||
|
+PKG_BUILD_PARALLEL:=0
|
||||||
|
+HOST_BUILD_PARALLEL:=0
|
||||||
|
|
||||||
|
# Variables used during configuration/build
|
||||||
|
HOST_PERL_PREFIX:=$(STAGING_DIR_HOSTPKG)/usr
|
Loading…
Reference in New Issue
Block a user