Skip to content
Snippets Groups Projects
Unverified Commit e51836ec authored by David Bauer's avatar David Bauer Committed by GitHub
Browse files

Merge pull request #2390 from freifunk-gluon/v2021.1.x-backports

Backports for v2021.1.x 
parents 7e7dfcea 0da2a7c4
Branches
Tags
No related merge requests found
Showing
with 223 additions and 119 deletions
...@@ -10,7 +10,7 @@ jobs: ...@@ -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: ...@@ -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
......
...@@ -19,8 +19,9 @@ escape = '$(subst ','\'',$(1))' ...@@ -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 ...@@ -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() ...@@ -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 ...@@ -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 ...@@ -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 * ...@@ -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 * ...@@ -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) { ...@@ -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) { ...@@ -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;
} }
<%- <%-
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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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>
......
"use strict";!function(){var r=JSON.parse(document.body.getAttribute("data-translations"));function i(t,e){return t.toFixed(e).replace(/\./,r["."])}function o(t,e){e--;for(var n=t;10<=n&&0<e;n/=10)e--;return i(t,e)}function a(t){return function(t,e,n){var i=0;if(void 0===n)return"- ";for(;e<n&&i<t.length-1;)n/=e,i++;return(n=o(n,3))+" "+t[i]}(["","K","M","G","T"],1024,t)}String.prototype.sprintf=function(){var t=0,e=arguments;return this.replace(/%s/g,function(){return e[t++]})};var s={id:function(t){return t},decimal:function(t){return i(t,2)},percent:function(t){return r["%s used"].sprintf(o(100*t,3)+"%")},memory:function(t){t=1-t.available/t.total;return s.percent(t)},time:function(t){var e=Math.round(t/60),n=Math.floor(e/1440),i=Math.floor(e%1440/60),e=Math.floor(e%60),t="";return 1===n?t+=r["1 day"]+", ":1<n&&(t+=r["%s days"].sprintf(n)+", "),t+=i+":",e<10&&(t+="0"),t+=e},packetsDiff:function(t,e,n){if(0<n)return n=(t-e)/n,r["%s packets/s"].sprintf(i(n,0))},bytesDiff:function(t,e,n){if(0<n)return a(8*((t-e)/n))+"bps"},bytes:function(t){return a(t)+"B"},neighbour:function(t){if(!t)return"";for(var e in c){var n=c[e].lookup_neigh(t);if(n)return"via "+n.get_hostname()+" ("+e+")"}return"via "+t+" (unknown iface)"}};function l(e,t){return t.split("/").forEach(function(t){e=e&&e[t]}),e}function d(t,e){var n=new EventSource(t),i={};n.onmessage=function(t){t=JSON.parse(t.data);e(t,i),i=t},n.onerror=function(){n.close(),window.setTimeout(function(){d(t,e)},3e3)}}var x,k=document.body.getAttribute("data-node-address");try{x=JSON.parse(document.body.getAttribute("data-node-location"))}catch(t){}function t(t){var e=document.getElementById("mesh-vpn");if(t){e.style.display="";for(var i=document.getElementById("mesh-vpn-peers");i.lastChild;)i.removeChild(i.lastChild);t=function e(n,i){return Object.keys(i.peers||{}).forEach(function(t){n.push([t,i.peers[t]])}),Object.keys(i.groups||{}).forEach(function(t){e(n,i.groups[t])}),n}([],t);t.sort(),t.forEach(function(t){var e=document.createElement("tr"),n=document.createElement("th");n.textContent=t[0],e.appendChild(n);n=document.createElement("td");t[1]?n.textContent=r.connected+" ("+s.time(t[1].established)+")":n.textContent=r["not connected"],e.appendChild(n),i.appendChild(e)})}else e.style.display="none"}function e(t){var e=document.getElementById("radios");if(t){e.style.display="";for(var i=document.getElementById("radio-devices");i.lastChild;)i.removeChild(i.lastChild);t.sort(function(t,e){return t.phy-e.phy}),t.forEach(function(t){var e=document.createElement("tr"),n=document.createElement("th");n.textContent="phy"+t.phy,e.appendChild(n);n=document.createElement("td");n.innerHTML=t.frequency+" MHz<br />Channel "+(2484===(t=t.frequency)?14:2412<=t&&t<=2472?(t-2407)/5:5160<=t&&t<=5885?(t-5e3)/5:"unknown"),e.appendChild(n),i.appendChild(e)})}else e.style.display="none"}var n=document.querySelectorAll("[data-statistics]");d("/cgi-bin/dyn/statistics",function(o,a){var c=o.uptime-a.uptime;n.forEach(function(t){var e=t.getAttribute("data-statistics"),n=t.getAttribute("data-format"),i=l(a,e),e=l(o,e);try{var r=s[n](e,i,c);void 0!==r&&(t.textContent=r)}catch(t){console.error(t)}});try{t(o.mesh_vpn)}catch(t){console.error(t)}try{e(o.wireless)}catch(t){console.error(t)}});var c={};function A(n){var i=document.createElement("canvas"),r=i.getContext("2d"),o=null;return{canvas:i,highlight:!1,resize:function(t,e){try{r.getImageData(0,0,t,e)}catch(t){}i.width=t,i.height=e},draw:function(t,e){e=e(o);r.clearRect(t,0,5,i.height),e&&(t=t,e=e,r.beginPath(),r.fillStyle=n,r.arc(t,e,1.2,0,2*Math.PI,!1),r.closePath(),r.fill())},set:function(t){o=t}}}function h(){var c=-100,s=0,n=0,i=[],l=document.createElement("canvas");l.className="signalgraph",l.height=200;var u=l.getContext("2d");function t(){l.width=l.clientWidth,i.forEach(function(t){t.resize(l.width,l.height)})}function r(){var e;0!==l.clientWidth&&(l.width!==l.clientWidth&&t(),u.clearRect(0,0,l.width,l.height),e=!1,i.forEach(function(t){t.highlight&&(e=!0)}),u.save(),i.forEach(function(t){e&&(u.globalAlpha=.2),t.highlight&&(u.globalAlpha=1),t.draw(n,function(t){return e=t,n=c,i=s,t=l.height,(1-(e-n)/(i-n))*t;var e,n,i}),u.drawImage(t.canvas,0,0)}),u.restore(),u.save(),u.beginPath(),u.strokeStyle="rgba(255, 180, 0, 0.15)",u.lineWidth=5,u.moveTo(n+2.5,0),u.lineTo(n+2.5,l.height),u.stroke(),function(){var t=Math.floor(l.height/40);u.save(),u.lineWidth=.5,u.strokeStyle="rgba(0, 0, 0, 0.25)",u.fillStyle="rgba(0, 0, 0, 0.5)",u.textAlign="end",u.textBaseline="bottom",u.beginPath();for(var e,n,i,r=0;r<t;r++){var o=l.height-40*r;u.moveTo(0,o-.5),u.lineTo(l.width,o-.5);var a=Math.round((e=o,n=c,i=s,a=l.height,(n*e+i*(a-e))/a))+" dBm";u.save(),u.strokeStyle="rgba(255, 255, 255, 0.9)",u.lineWidth=4,u.miterLimit=2,u.strokeText(a,l.width-5,o-2.5),u.fillText(a,l.width-5,o-2.5),u.restore()}u.stroke(),u.strokeStyle="rgba(0, 0, 0, 0.83)",u.lineWidth=1.5,u.strokeRect(.5,.5,l.width-1,l.height-1),u.restore()}())}t(),window.addEventListener("resize",r);var o=0;return window.requestAnimationFrame(function t(e){40<e-o&&(r(),n=(n+1)%l.width,o=e),window.requestAnimationFrame(t)}),{el:l,addSignal:function(t){i.push(t),t.resize(l.width,l.height)},removeSignal:function(t){i.splice(i.indexOf(t),1)}}}function f(t,e,n,i){var r,o=t.table.firstElementChild,a=t.table.insertRow(),c=a.insertCell();c.setAttribute("data-label",o.children[0].textContent),t.wireless&&((r=document.createElement("span")).textContent="",r.style.color=n,c.appendChild(r));var s=document.createElement("span");s.textContent=e,c.appendChild(s);var l={};for(var u,d,h,f,g,v,m,p,b,y=0;y<o.children.length;y++)u=o.children[y],f=h=d=void 0,(f=u.getAttribute("data-key"))&&(d=u.getAttribute("data-suffix")||"",(h=a.insertCell()).textContent="-",h.setAttribute("data-label",u.textContent),l[f]={td:h,suffix:d});function C(){b&&window.clearTimeout(b),b=window.setTimeout(function(){p&&t.signalgraph.removeSignal(p),a.parentNode.removeChild(a),i()},6e4)}function E(t){t=function(t){"::"==(t="::"==t.slice(0,2)?"0"+t:t).slice(-2)&&(t+="0");var n=(t=t.split(":")).length,i=[];return t.forEach(function(t,e){if(""===t)for(;n++<=8;)i.push(0);else/^[a-f0-9]{1,4}$/i.test(t)&&i.push(parseInt(t,16))}),i}(t);if(t){var e="";return t.forEach(function(t){e+=("0000000000000000"+t.toString(2)).slice(-16)}),e}}function w(t){var i=E(k);if(t&&t[0]){(t=t.map(function(t){var e=E(t);if(!e)return[-1];var n=0;return[n=i?function(t,e){for(var n=0;n<t.length&&n<e.length&&t[n]===e[n];n++);return n}(i,e):n,e,t]})).sort(function(t,e){return t[0]<e[0]?1:t[0]>e[0]||t[1]<e[1]?-1:t[1]>e[1]?1:0});t=t[0][2];return t&&!/^fe80:/i.test(t)?t:void 0}}return t.wireless&&((g=a.insertCell()).textContent="-",g.setAttribute("data-label",o.children[Object.keys(l).length+1].textContent),(v=a.insertCell()).textContent="-",v.setAttribute("data-label",o.children[Object.keys(l).length+2].textContent),(m=a.insertCell()).textContent="-",m.setAttribute("data-label",o.children[Object.keys(l).length+3].textContent),p=A(n),t.signalgraph.addSignal(p)),a.onmouseenter=function(){a.classList.add("highlight"),p&&(p.highlight=!0)},a.onmouseleave=function(){a.classList.remove("highlight"),p&&(p.highlight=!1)},C(),{get_hostname:function(){return s.textContent},update_nodeinfo:function(t){var e,n,i,r,o=w(t.network.addresses);o&&("span"===s.nodeName.toLowerCase()&&(r=s,s=document.createElement("a"),r.parentNode.replaceChild(s,r)),s.href="http://["+o+"]/"),s.textContent=t.hostname,x&&t.location&&(e=x.latitude,n=x.longitude,i=t.location.latitude,r=t.location.longitude,o=Math.PI/180,t=(i*=o)-(e*=o),n=(r*=o)-(n*=o),i=Math.sin(t/2)*Math.sin(t/2)+Math.sin(n/2)*Math.sin(n/2)*Math.cos(e)*Math.cos(i),i=6372.8*(2*Math.asin(Math.sqrt(i))),v.textContent=Math.round(1e3*i)+" m"),C()},update_mesh:function(n){Object.keys(l).forEach(function(t){var e=l[t];e.td.textContent=n[t]+e.suffix}),C()},update_wifi:function(t){g.textContent=t.signal,m.textContent=Math.round(t.inactive/1e3)+" s",a.classList.toggle("inactive",200<t.inactive),p.set(200<t.inactive?null:t.signal),C()}}}function u(t,e,n){var i,o={};n&&(i=h(),t.appendChild(i.el));var r={table:t.firstElementChild,signalgraph:i,ifname:e,wireless:n},a=!1,c={},s=[];function l(){var t;a||(a=!0,(t=new EventSource("/cgi-bin/dyn/neighbours-nodeinfo?"+encodeURIComponent(e))).addEventListener("neighbour",function(t){try{var n=JSON.parse(t.data);i=[],r=n.network.mesh,Object.keys(r).forEach(function(t){var e=r[t].interfaces;Object.keys(e).forEach(function(t){e[t].forEach(function(t){i.push(t)})})}),i.forEach(function(t){var e=o[t];if(e){delete c[t];try{e.update_nodeinfo(n)}catch(t){console.error(t)}}})}catch(t){console.error(t)}var i,r},!1),t.onerror=function(){t.close(),a=!1,Object.keys(c).forEach(function(t){0<c[t]&&(c[t]--,l())})})}function u(t){var e=o[t];return e||(c[t]=3,e=o[t]=f(r,t,(s=s[0]?s:["#396AB1","#DA7C30","#3E9651","#CC2529","#535154","#6B4C9A","#922428","#948B3D"]).shift(),function(){delete c[t],delete o[t]}),l()),e}return n&&d("/cgi-bin/dyn/stations?"+encodeURIComponent(e),function(n){Object.keys(n).forEach(function(t){var e=n[t];u(t).update_wifi(e)})}),{get_neigh:u,lookup_neigh:function(t){return o[t]}}}document.querySelectorAll("[data-interface]").forEach(function(t){var e=t.getAttribute("data-interface"),n=(t.getAttribute("data-interface-address"),!!t.getAttribute("data-interface-wireless"));c[e]=u(t,e,n)});var g=document.body.getAttribute("data-mesh-provider");g&&d(g,function(i){Object.keys(i).forEach(function(t){var e=i[t],n=c[e.ifname];n&&n.get_neigh(t).update_mesh(e)})})}(); "use strict";!function(){var i=JSON.parse(document.body.getAttribute("data-translations"));function r(t,e){return t.toFixed(e).replace(/\./,i["."])}function a(t,e){e--;for(var n=t;10<=n&&0<e;n/=10)e--;return r(t,e)}function o(t){return function(t,e,n){var r=0;if(void 0===n)return"- ";for(;e<n&&r<t.length-1;)n/=e,r++;return(n=a(n,3))+" "+t[r]}(["","K","M","G","T"],1024,t)}String.prototype.sprintf=function(){var t=0,e=arguments;return this.replace(/%s/g,function(){return e[t++]})};var u={id:function(t){return t},decimal:function(t){return r(t,2)},percent:function(t){return i["%s used"].sprintf(a(100*t,3)+"%")},memory:function(t){t=1-t.available/t.total;return u.percent(t)},time:function(t){var e=Math.round(t/60),n=Math.floor(e/1440),r=Math.floor(e%1440/60),e=Math.floor(e%60),t="";return 1===n?t+=i["1 day"]+", ":1<n&&(t+=i["%s days"].sprintf(n)+", "),t+=r+":",e<10&&(t+="0"),t+=e},packetsDiff:function(t,e,n){if(0<n)return n=(t-e)/n,i["%s packets/s"].sprintf(r(n,0))},bytesDiff:function(t,e,n){if(0<n)return o(8*((t-e)/n))+"bps"},bytes:function(t){return o(t)+"B"},neighbour:function(t){if(!t)return"";for(var e in c){var n=c[e].lookup_neigh(t);if(n){var r=document.createElement("span");r.appendChild(document.createTextNode("via "));var i=document.createElement("a");return i.href="http://["+n.get_addr()+"]/",i.textContent=n.get_hostname(),r.appendChild(i),r.appendChild(document.createTextNode(" ("+e+")")),r}}return"via "+t+" (unknown iface)"}};function s(e,t){return t.split("/").forEach(function(t){e=e&&e[t]}),e}function d(t,e){var n=new EventSource(t),r={};n.onmessage=function(t){t=JSON.parse(t.data);e(t,r),r=t},n.onerror=function(){n.close(),window.setTimeout(function(){d(t,e)},3e3)}}var x,k=document.body.getAttribute("data-node-address");try{x=JSON.parse(document.body.getAttribute("data-node-location"))}catch(t){}function t(t){var e=document.getElementById("mesh-vpn");if(t){e.style.display="";for(var r=document.getElementById("mesh-vpn-peers");r.lastChild;)r.removeChild(r.lastChild);t=function e(n,r){return Object.keys(r.peers||{}).forEach(function(t){n.push([t,r.peers[t]])}),Object.keys(r.groups||{}).forEach(function(t){e(n,r.groups[t])}),n}([],t);t.sort(),t.forEach(function(t){var e=document.createElement("tr"),n=document.createElement("th");n.textContent=t[0],e.appendChild(n);n=document.createElement("td");t[1]?n.textContent=i.connected+" ("+u.time(t[1].established)+")":n.textContent=i["not connected"],e.appendChild(n),r.appendChild(e)})}else e.style.display="none"}var e=document.querySelectorAll("[data-statistics]");d("/cgi-bin/dyn/statistics",function(a,o){var c=a.uptime-o.uptime;e.forEach(function(t){var e=t.getAttribute("data-statistics"),n=t.getAttribute("data-format"),r=s(o,e),e=s(a,e);try{var i=u[n](e,r,c);"object"==typeof i?(t.lastChild&&t.removeChild(t.lastChild),t.appendChild(i)):t.textContent=i}catch(t){console.error(t)}});try{t(a.mesh_vpn)}catch(t){console.error(t)}});var c={};function A(n){var r=document.createElement("canvas"),i=r.getContext("2d"),a=null;return{canvas:r,highlight:!1,resize:function(t,e){var n;try{n=i.getImageData(0,0,t,e)}catch(t){}r.width=t,r.height=e,n&&i.putImageData(n,0,0)},draw:function(t,e){e=e(a);i.clearRect(t,0,5,r.height),e&&(t=t,e=e,i.beginPath(),i.fillStyle=n,i.arc(t,e,1.2,0,2*Math.PI,!1),i.closePath(),i.fill())},set:function(t){a=t}}}function h(){var i=-100,a=0,n=0,r=[],o=document.createElement("canvas");o.className="signalgraph",o.height=200;var c=o.getContext("2d");function t(){o.width=o.clientWidth,r.forEach(function(t){t.resize(o.width,o.height)})}function u(){var e;0!==o.clientWidth&&(o.width!==o.clientWidth&&t(),c.clearRect(0,0,o.width,o.height),e=!1,r.forEach(function(t){t.highlight&&(e=!0)}),c.save(),r.forEach(function(t){e&&(c.globalAlpha=.2),t.highlight&&(c.globalAlpha=1),t.draw(n,function(t){return e=o.height,(1-(t-i)/(a-i))*e;var e}),c.drawImage(t.canvas,0,0)}),c.restore(),c.save(),c.beginPath(),c.strokeStyle="rgba(255, 180, 0, 0.15)",c.lineWidth=5,c.moveTo(n+2.5,0),c.lineTo(n+2.5,o.height),c.stroke(),function(){var t=Math.floor(o.height/40);c.save(),c.lineWidth=.5,c.strokeStyle="rgba(0, 0, 0, 0.25)",c.fillStyle="rgba(0, 0, 0, 0.5)",c.textAlign="end",c.textBaseline="bottom",c.beginPath();for(var e=0;e<t;e++){var n=o.height-40*e;c.moveTo(0,n-.5),c.lineTo(o.width,n-.5);var r=Math.round((r=o.height,(i*n+a*(r-n))/r))+" dBm";c.save(),c.strokeStyle="rgba(255, 255, 255, 0.9)",c.lineWidth=4,c.miterLimit=2,c.strokeText(r,o.width-5,n-2.5),c.fillText(r,o.width-5,n-2.5),c.restore()}c.stroke(),c.strokeStyle="rgba(0, 0, 0, 0.83)",c.lineWidth=1.5,c.strokeRect(.5,.5,o.width-1,o.height-1),c.restore()}())}t(),window.addEventListener("resize",u);var s=0;return window.requestAnimationFrame(function t(e){40<e-s&&(u(),n=(n+1)%o.width,s=e),window.requestAnimationFrame(t)}),{el:o,addSignal:function(t){r.push(t),t.resize(o.width,o.height)},removeSignal:function(t){r.splice(r.indexOf(t),1)}}}function f(t,o,e,n){var r,i=t.table.firstElementChild,a=t.table.insertRow(),c=a.insertCell();c.setAttribute("data-label",i.children[0].textContent),t.wireless&&((r=document.createElement("span")).textContent="",r.style.color=e,c.appendChild(r));var u=document.createElement("span");u.textContent=o,c.appendChild(u);var s={};for(var l,d,h,f,g,v,p,m,b,C=0;C<i.children.length;C++)l=i.children[C],f=h=d=void 0,(f=l.getAttribute("data-key"))&&(d=l.getAttribute("data-suffix")||"",(h=a.insertCell()).textContent="-",h.setAttribute("data-label",l.textContent),s[f]={td:h,suffix:d});function y(){b&&window.clearTimeout(b),b=window.setTimeout(function(){m&&t.signalgraph.removeSignal(m),a.parentNode.removeChild(a),n()},6e4)}function w(t){t=function(t){"::"==(t="::"==t.slice(0,2)?"0"+t:t).slice(-2)&&(t+="0");for(var e=t.split(":"),n=e.length,r=[],i=0;i<e.length;i++){var a=e[i];if(""===a)for(;n++<=8;)r.push(0);else{if(!/^[a-f0-9]{1,4}$/i.test(a))return;r.push(parseInt(a,16))}}return r}(t);if(t){var e="";return t.forEach(function(t){e+=("0000000000000000"+t.toString(2)).slice(-16)}),e}}function E(t){var r=w(k);if(t&&t[0]){(t=t.map(function(t){var e=w(t);if(!e)return[-1];var n=0;return[n=r?function(t,e){for(var n=0;n<t.length&&n<e.length&&t[n]===e[n];n++);return n}(r,e):n,e,t]})).sort(function(t,e){return t[0]<e[0]?1:t[0]>e[0]||t[1]<e[1]?-1:t[1]>e[1]?1:0});t=t[0][2];return t&&!/^fe80:/i.test(t)?t:void 0}}return t.wireless&&((g=a.insertCell()).textContent="-",g.setAttribute("data-label",i.children[Object.keys(s).length+1].textContent),(v=a.insertCell()).textContent="-",v.setAttribute("data-label",i.children[Object.keys(s).length+2].textContent),(p=a.insertCell()).textContent="-",p.setAttribute("data-label",i.children[Object.keys(s).length+3].textContent),m=A(e),t.signalgraph.addSignal(m)),a.onmouseenter=function(){a.classList.add("highlight"),m&&(m.highlight=!0)},a.onmouseleave=function(){a.classList.remove("highlight"),m&&(m.highlight=!1)},y(),{get_hostname:function(){return u.textContent},get_addr:function(){return o},update_nodeinfo:function(t){var e,n,r,i,a;(o=E(t.network.addresses))&&("span"===u.nodeName.toLowerCase()&&(a=u,u=document.createElement("a"),a.parentNode.replaceChild(u,a)),u.href="http://["+o+"]/"),u.textContent=t.hostname,x&&t.location&&(e=x.latitude,n=x.longitude,r=t.location.latitude,i=t.location.longitude,a=Math.PI/180,t=(r*=a)-(e*=a),n=(i*=a)-(n*=a),r=Math.sin(t/2)*Math.sin(t/2)+Math.sin(n/2)*Math.sin(n/2)*Math.cos(e)*Math.cos(r),r=6372.8*(2*Math.asin(Math.sqrt(r))),v.textContent=Math.round(1e3*r)+" m"),y()},update_mesh:function(n){Object.keys(s).forEach(function(t){var e=s[t];e.td.textContent=n[t]+e.suffix}),y()},update_wifi:function(t){g.textContent=t.signal,p.textContent=Math.round(t.inactive/1e3)+" s",a.classList.toggle("inactive",200<t.inactive),m.set(200<t.inactive?null:t.signal),y()}}}function l(t,e,n){var r,a={};n&&(r=h(),t.appendChild(r.el));var i={table:t.firstElementChild,signalgraph:r,ifname:e,wireless:n},o=!1,c={},u=[];function s(){var t;o||(o=!0,(t=new EventSource("/cgi-bin/dyn/neighbours-nodeinfo?"+encodeURIComponent(e))).addEventListener("neighbour",function(t){try{var n=JSON.parse(t.data);r=[],i=n.network.mesh,Object.keys(i).forEach(function(t){var e=i[t].interfaces;Object.keys(e).forEach(function(t){e[t].forEach(function(t){r.push(t)})})}),r.forEach(function(t){var e=a[t];if(e){delete c[t];try{e.update_nodeinfo(n)}catch(t){console.error(t)}}})}catch(t){console.error(t)}var r,i},!1),t.onerror=function(){t.close(),o=!1,Object.keys(c).forEach(function(t){0<c[t]&&(c[t]--,s())})})}function l(t){var e=a[t];return e||(c[t]=3,e=a[t]=f(i,t,(u=u[0]?u:["#396AB1","#DA7C30","#3E9651","#CC2529","#535154","#6B4C9A","#922428","#948B3D"]).shift(),function(){delete c[t],delete a[t]}),s()),e}return n&&d("/cgi-bin/dyn/stations?"+encodeURIComponent(e),function(n){Object.keys(n).forEach(function(t){var e=n[t];l(t).update_wifi(e)})}),{get_neigh:l,lookup_neigh:function(t){return a[t]}}}document.querySelectorAll("[data-interface]").forEach(function(t){var e=t.getAttribute("data-interface"),n=(t.getAttribute("data-interface-address"),!!t.getAttribute("data-interface-wireless"));c[e]=l(t,e,n)});var n=document.body.getAttribute("data-mesh-provider");n&&d(n,function(r){Object.keys(r).forEach(function(t){var e=r[t],n=c[e.ifname];n&&n.get_neigh(t).update_mesh(e)})})}();
\ No newline at end of file \ No newline at end of file
...@@ -31,8 +31,8 @@ msgstr "Automatische Updates" ...@@ -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 "" ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -596,7 +564,7 @@
groups.push(parseInt(part, 16)); groups.push(parseInt(part, 16));
} }
}); };
return groups; return groups;
} }
...@@ -664,8 +632,11 @@ ...@@ -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) ...@@ -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$ ...@@ -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 ...@@ -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>
<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%>">
......
<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 @@ ...@@ -41,4 +42,5 @@
}); });
}); });
})(); })();
//]]>
</script> </script>
...@@ -4,7 +4,8 @@ local util = require "gluon.web.util" ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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
if not msg.mime_boundary then
return nil, "Invalid Content-Type found"
end 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) ...@@ -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) ...@@ -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
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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment