From: Pau Escrich
Date: Sun, 26 Mar 2017 00:32:29 +0000 (+0100)
Subject: luci-app-bmx: Redesign Makefile. Split JS libraries. Clean package
X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=e912da66254eaf98e0a053815d2b1b437753d5bd;p=feed%2Frouting.git
luci-app-bmx: Redesign Makefile. Split JS libraries. Clean package
Add luci-lib-jquery-1-4 and luci-lib-dracula packages. Remove unused library Curry.
Signed-off-by: Pau Escrich
---
diff --git a/luci-app-bmx6/Makefile b/luci-app-bmx6/Makefile
index ec69d2d..88db9d5 100644
--- a/luci-app-bmx6/Makefile
+++ b/luci-app-bmx6/Makefile
@@ -20,7 +20,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-bmx6
-PKG_RELEASE:=3
+PKG_RELEASE:=4
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
PKG_LICENSE:=GPL-2.0+
@@ -32,14 +32,40 @@ define Package/luci-app-bmx6
CATEGORY:=LuCI
SUBMENU:=3. Applications
TITLE:= bmx6 configuration, status and visualization module
- DEPENDS:=+luci-lib-json +luci-mod-admin-full +luci-lib-httpclient +bmx6
+ DEPENDS:=+luci-lib-json +luci-mod-admin-full +luci-lib-httpclient +bmx6 +luci-lib-jquery-1-4 +luci-lib-dracula
MAINTAINER:= Pau Escrich
endef
+define Package/luci-lib-jquery-1-4
+ SECTION:=luci
+ CATEGORY:=LuCI
+ TITLE:=LuCI - Lua Configuration Interface
+ MAINTAINER:=Gui Iribarren
+ SUBMENU:=6. Libraries
+ TITLE:=jQuery 1.4 javascript library
+endef
+
+define Package/luci-lib-dracula
+ SECTION:=luci
+ CATEGORY:=LuCI
+ TITLE:=LuCI - Lua Configuration Interface
+ MAINTAINER:=Pau Escrich
+ SUBMENU:=6. Libraries
+ TITLE:=dracula graph javascript library
+endef
+
define Package/luci-app-bmx6/description
bmx6 web application (status and configuration) for LuCi web interface
endef
+define Package/luci-lib-jquery-1-4/description
+ minified javascript jQuery 1.4 library
+endef
+
+define Package/luci-lib-dracula-graph/description
+ minified dracula javascript graph library
+endef
+
define Package/luci-app-bmx6/conffiles
/etc/config/luci-bmx6
endef
@@ -54,9 +80,20 @@ define Build/Compile
endef
define Package/luci-app-bmx6/install
- $(CP) ./files/* $(1)/
+ $(CP) ./bmx6/* $(1)/
chmod 755 $(1)/www/cgi-bin/bmx6-info
endef
-$(eval $(call BuildPackage,luci-app-bmx6))
+define Package/luci-lib-jquery-1-4/install
+ $(INSTALL_DIR) $(1)/www/luci-static/resources/jquery/
+ $(CP) ./jquery/* $(1)/www/luci-static/resources/jquery/
+endef
+
+define Package/luci-lib-dracula/install
+ $(INSTALL_DIR) $(1)/www/luci-static/resources/dracula
+ $(CP) ./dracula/* $(1)/www/luci-static/resources/dracula/
+endef
+$(eval $(call BuildPackage,luci-app-bmx6))
+$(eval $(call BuildPackage,luci-lib-jquery-1-4))
+$(eval $(call BuildPackage,luci-lib-dracula))
diff --git a/luci-app-bmx6/bmx6/etc/config/luci-bmx6 b/luci-app-bmx6/bmx6/etc/config/luci-bmx6
new file mode 100644
index 0000000..df1e715
--- /dev/null
+++ b/luci-app-bmx6/bmx6/etc/config/luci-bmx6
@@ -0,0 +1,7 @@
+config 'bmx6' 'luci'
+ option ignore '0'
+ option place 'admin network BMX6'
+ #option place 'qmp Mesh'
+ option position '3'
+ #option json 'http://127.0.0.1/cgi-bin/bmx6-info?'
+ option json 'exec:/www/cgi-bin/bmx6-info -s'
diff --git a/luci-app-bmx6/bmx6/usr/lib/lua/luci/controller/bmx6.lua b/luci-app-bmx6/bmx6/usr/lib/lua/luci/controller/bmx6.lua
new file mode 100644
index 0000000..5842fc9
--- /dev/null
+++ b/luci-app-bmx6/bmx6/usr/lib/lua/luci/controller/bmx6.lua
@@ -0,0 +1,277 @@
+--[[
+ Copyright (C) 2011 Pau Escrich
+ Contributors Jo-Philipp Wich
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+--]]
+
+local bmx6json = require("luci.model.bmx6json")
+
+module("luci.controller.bmx6", package.seeall)
+
+function index()
+ local place = {}
+ local ucim = require "luci.model.uci"
+ local uci = ucim.cursor()
+
+ -- checking if ignore is on
+ if uci:get("luci-bmx6","luci","ignore") == "1" then
+ return nil
+ end
+
+ -- getting value from uci database
+ local uci_place = uci:get("luci-bmx6","luci","place")
+
+ -- default values
+ if uci_place == nil then
+ place = {"bmx6"}
+ else
+ local util = require "luci.util"
+ place = util.split(uci_place," ")
+ end
+
+ -- getting position of menu
+ local uci_position = uci:get("luci-bmx6","luci","position")
+
+ ---------------------------
+ -- Starting with the pages
+ ---------------------------
+
+ --- status (default)
+ entry(place,call("action_nodes_j"),place[#place],tonumber(uci_position))
+
+ table.insert(place,"Status")
+ entry(place,call("action_status_j"),"Status",0)
+ table.remove(place)
+
+ --- nodes
+ table.insert(place,"Nodes")
+ entry(place,call("action_nodes_j"),"Nodes",1)
+ table.remove(place)
+
+ --- links
+ table.insert(place,"Links")
+ entry(place,call("action_links"),"Links",2).leaf = true
+ table.remove(place)
+
+ -- Tunnels
+ table.insert(place,"Tunnels")
+ entry(place,call("action_tunnels_j"), "Tunnels", 3).leaf = true
+ table.remove(place)
+
+ --- Chat
+ table.insert(place,"Chat")
+ entry(place,call("action_chat"),"Chat",5)
+ table.remove(place)
+
+ --- Graph
+ table.insert(place,"Graph")
+ entry(place, template("bmx6/graph"), "Graph",4)
+ table.remove(place)
+
+ --- Topology (hidden)
+ table.insert(place,"topology")
+ entry(place, call("action_topology"), nil)
+ table.remove(place)
+
+ --- configuration (CBI)
+ table.insert(place,"Configuration")
+ entry(place, cbi("bmx6/main"), "Configuration",6).dependent=false
+
+ table.insert(place,"General")
+ entry(place, cbi("bmx6/main"), "General",1)
+ table.remove(place)
+
+ table.insert(place,"Advanced")
+ entry(place, cbi("bmx6/advanced"), "Advanced",5)
+ table.remove(place)
+
+ table.insert(place,"Interfaces")
+ entry(place, cbi("bmx6/interfaces"), "Interfaces",2)
+ table.remove(place)
+
+ table.insert(place,"Tunnels")
+ entry(place, cbi("bmx6/tunnels"), "Tunnels",3)
+ table.remove(place)
+
+ table.insert(place,"Plugins")
+ entry(place, cbi("bmx6/plugins"), "Plugins",6)
+ table.remove(place)
+
+ table.insert(place,"HNAv6")
+ entry(place, cbi("bmx6/hna"), "HNAv6",4)
+ table.remove(place)
+
+ table.remove(place)
+
+end
+
+function action_status_j()
+ luci.template.render("bmx6/status_j", {})
+end
+
+
+function action_nodes_j()
+ local http = require "luci.http"
+ local link_non_js = "/cgi-bin/luci" .. http.getenv("PATH_INFO") .. '/nodes_nojs'
+
+ luci.template.render("bmx6/nodes_j", {link_non_js=link_non_js})
+end
+
+function action_gateways_j()
+ luci.template.render("bmx6/gateways_j", {})
+end
+
+function action_tunnels_j()
+ luci.template.render("bmx6/tunnels_j", {})
+end
+
+function action_links(host)
+ local links = bmx6json.get("links", host)
+ local devlinks = {}
+ local _,l
+
+ if links ~= nil then
+ links = links.links
+ for _,l in ipairs(links) do
+ devlinks[l.viaDev] = {}
+ end
+ for _,l in ipairs(links) do
+ l.name = luci.util.split(l.name,'.')[1]
+ table.insert(devlinks[l.viaDev],l)
+ end
+ end
+
+ luci.template.render("bmx6/links", {links=devlinks})
+end
+
+function action_topology()
+ local originators = bmx6json.get("originators/all")
+ local o,i,l,i2
+ local first = true
+ local topology = '[ '
+ local cache = '/tmp/bmx6-topology.json'
+ local offset = 60
+
+ local cachefd = io.open(cache,r)
+ local update = false
+
+ if cachefd ~= nil then
+ local lastupdate = tonumber(cachefd:read("*line")) or 0
+ if os.time() >= lastupdate + offset then
+ update = true
+ else
+ topology = cachefd:read("*all")
+ end
+ cachefd:close()
+ end
+
+ if cachefd == nil or update then
+ for i,o in ipairs(originators) do
+ local links = bmx6json.get("links",o.primaryIp)
+ if links then
+ if first then
+ first = false
+ else
+ topology = topology .. ', '
+ end
+
+ topology = topology .. '{ "name": "%s", "links": [' %o.name
+
+ local first2 = true
+
+ for i2,l in ipairs(links.links) do
+ if first2 then
+ first2 = false
+ else
+ topology = topology .. ', '
+ end
+ name = l.name or l.llocalIp or "unknown"
+ topology = topology .. '{ "name": "%s", "rxRate": %s, "txRate": %s }'
+ %{ name, l.rxRate, l.txRate }
+
+ end
+
+ topology = topology .. ']}'
+ end
+
+ end
+
+ topology = topology .. ' ]'
+
+ -- Upgrading the content of the cache file
+ cachefd = io.open(cache,'w+')
+ cachefd:write(os.time()..'\n')
+ cachefd:write(topology)
+ cachefd:close()
+ end
+
+ luci.http.prepare_content("application/json")
+ luci.http.write(topology)
+end
+
+
+function action_chat()
+ local sms_dir = "/var/run/bmx6/sms"
+ local rcvd_dir = sms_dir .. "/rcvdSms"
+ local send_file = sms_dir .. "/sendSms/chat"
+ local sms_list = bmx6json.get("rcvdSms")
+ local sender = ""
+ local sms_file = ""
+ local chat = {}
+ local to_send = nil
+ local sent = ""
+ local fd = nil
+
+ if luci.sys.call("test -d " .. sms_dir) ~= 0 then
+ luci.template.render("bmx6/error", {txt="sms plugin disabled or some problem with directory " .. sms_dir})
+ return nil
+ end
+
+ sms_list = luci.util.split(luci.util.exec("ls "..rcvd_dir.."/*:chat"))
+
+ for _,sms_path in ipairs(sms_list) do
+ if #sms_path > #rcvd_dir then
+ sms_file = luci.util.split(sms_path,'/')
+ sms_file = sms_file[#sms_file]
+ sender = luci.util.split(sms_file,':')[1]
+
+ -- Trying to clean the name
+ if string.find(sender,".") ~= nil then
+ sender = luci.util.split(sender,".")[1]
+ end
+
+ fd = io.open(sms_path,"r")
+ chat[sender] = fd:read()
+ fd:close()
+ end
+ end
+
+ to_send = luci.http.formvalue("toSend")
+ if to_send ~= nil and #to_send > 1 then
+ fd = io.open(send_file,"w")
+ fd:write(to_send)
+ fd:close()
+ sent = to_send
+ else
+ sent = luci.util.exec("cat "..send_file)
+ end
+
+ luci.template.render("bmx6/chat", {chat=chat,sent=sent})
+end
+
diff --git a/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/bmx6json.lua b/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/bmx6json.lua
new file mode 100644
index 0000000..a4a8e43
--- /dev/null
+++ b/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/bmx6json.lua
@@ -0,0 +1,223 @@
+--[[
+ Copyright (C) 2011 Pau Escrich
+ Contributors Jo-Philipp Wich
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+--]]
+
+local ltn12 = require("luci.ltn12")
+local json = require("luci.json")
+local util = require("luci.util")
+local uci = require("luci.model.uci")
+local sys = require("luci.sys")
+local template = require("luci.template")
+local http = require("luci.http")
+local string = require("string")
+local table = require("table")
+local nixio = require("nixio")
+local nixiofs = require("nixio.fs")
+local ipairs = ipairs
+
+module "luci.model.bmx6json"
+
+-- Returns a LUA object from bmx6 JSON daemon
+
+function get(field, host)
+ local url
+ if host ~= nil then
+ if host:match(":") then
+ url = 'http://[%s]/cgi-bin/bmx6-info?' % host
+ else
+ url = 'http://%s/cgi-bin/bmx6-info?' % host
+ end
+ else
+ url = uci.cursor():get("luci-bmx6","luci","json")
+ end
+
+ if url == nil then
+ print_error("bmx6 json url not configured, cannot fetch bmx6 daemon data",true)
+ return nil
+ end
+
+ local json_url = util.split(url,":")
+ local raw = ""
+
+ if json_url[1] == "http" then
+ raw,err = wget(url..field,1000)
+ else
+
+ if json_url[1] == "exec" then
+ raw = sys.exec(json_url[2]..' '..field)
+ else
+ print_error("bmx6 json url not recognized, cannot fetch bmx6 daemon data. Use http: or exec:",true)
+ return nil
+ end
+
+ end
+
+ local data = nil
+
+ if raw and raw:len() > 10 then
+ local decoder = json.Decoder()
+ ltn12.pump.all(ltn12.source.string(raw), decoder:sink())
+ data = decoder:get()
+-- else
+-- print_error("Cannot get data from bmx6 daemon",true)
+-- return nil
+ end
+
+ return data
+end
+
+function print_error(txt,popup)
+ util.perror(txt)
+ sys.call("logger -t bmx6json " .. txt)
+
+ if popup then
+ http.write('')
+ else
+ http.write("
')
+ end
+
+end
+
+function text2html(txt)
+ txt = string.gsub(txt,"<","{")
+ txt = string.gsub(txt,">","}")
+ txt = util.striptags(txt)
+ return txt
+end
+
+
+function wget(url, timeout)
+ local rfd, wfd = nixio.pipe()
+ local pid = nixio.fork()
+ if pid == 0 then
+ rfd:close()
+ nixio.dup(wfd, nixio.stdout)
+ -- candidates for wget, try first ones with SSL support
+ local candidates = {{"/usr/bin/wget-ssl",1},{"/usr/bin/wget",0},{"/bin/wget",0}}
+ local _, bin
+ for _, bin in ipairs(candidates) do
+ if nixiofs.access(bin[1], "x") then
+ if bin[2] == 0 then
+ nixio.exec(bin[1], "-q", "-O", "-", url)
+ else
+ nixio.exec(bin[1], "--no-check-certificate", "-q", "-O", "-", url)
+ end
+ end
+ end
+ return
+ else
+ wfd:close()
+ rfd:setblocking(false)
+
+ local buffer = { }
+ local err1, err2
+
+ while true do
+ local ready = nixio.poll({{ fd = rfd, events = nixio.poll_flags("in") }}, timeout)
+ if not ready then
+ nixio.kill(pid, nixio.const.SIGKILL)
+ err1 = "timeout"
+ break
+ end
+
+ local rv = rfd:read(4096)
+ if rv then
+ -- eof
+ if #rv == 0 then
+ break
+ end
+
+ buffer[#buffer+1] = rv
+ else
+ -- error
+ if nixio.errno() ~= nixio.const.EAGAIN and
+ nixio.errno() ~= nixio.const.EWOULDBLOCK then
+ err1 = "error"
+ err2 = nixio.errno()
+ end
+ end
+ end
+
+ nixio.waitpid(pid, "nohang")
+ if not err1 then
+ return table.concat(buffer)
+ else
+ return nil, err1, err2
+ end
+ end
+end
+
+function getOptions(name)
+ -- Getting json and Checking if bmx6-json is avaiable
+ local options = get("options")
+ if options == nil or options.OPTIONS == nil then
+ m.message = "bmx6-json plugin is not running or some mistake in luci-bmx6 configuration, check /etc/config/luci-bmx6"
+ return nil
+ else
+ options = options.OPTIONS
+ end
+
+ -- Filtering by the option name
+ local i,_
+ local namedopt = nil
+ if name ~= nil then
+ for _,i in ipairs(options) do
+ if i.name == name and i.CHILD_OPTIONS ~= nil then
+ namedopt = i.CHILD_OPTIONS
+ break
+ end
+ end
+ end
+
+ return namedopt
+end
+
+-- Rturns a help string formated to be used in HTML scope
+function getHtmlHelp(opt)
+ if opt == nil then return nil end
+
+ local help = ""
+ if opt.help ~= nil then
+ help = text2html(opt.help)
+ end
+ if opt.syntax ~= nil then
+ help = help .. " Syntax: " .. text2html(opt.syntax)
+ end
+
+ return help
+end
+
+function testandreload()
+ local test = sys.call('bmx6 -c --test > /tmp/bmx6-luci.err.tmp')
+ if test ~= 0 then
+ return sys.exec("cat /tmp/bmx6-luci.err.tmp")
+ end
+
+ local err = sys.call('bmx6 -c --configReload > /tmp/bmx6-luci.err.tmp')
+ if err ~= 0 then
+ return sys.exec("cat /tmp/bmx6-luci.err.tmp")
+ end
+
+ return nil
+end
+
diff --git a/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/cbi/bmx6/advanced.lua b/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/cbi/bmx6/advanced.lua
new file mode 100644
index 0000000..c254899
--- /dev/null
+++ b/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/cbi/bmx6/advanced.lua
@@ -0,0 +1,75 @@
+--[[
+ Copyright (C) 2011 Pau Escrich
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+--]]
+
+m = Map("bmx6", "bmx6")
+
+local bmx6json = require("luci.model.bmx6json")
+local util = require("luci.util")
+local http = require("luci.http")
+local sys = require("luci.sys")
+
+local options = bmx6json.get("options")
+if options == nil or options.OPTIONS == nil then
+ m.message = "bmx6-json plugin is not running or some mistake in luci-bmx6 configuration, check /etc/config/luci-bmx6"
+ options = {}
+else
+ options = options.OPTIONS
+end
+
+local general = m:section(NamedSection,"general","bmx6")
+general.addremove = true
+
+local name = ""
+local help = ""
+local value = nil
+local _,o
+
+for _,o in ipairs(options) do
+ if o.name ~= nil and o.CHILD_OPTIONS == nil and o.configurable == 1 then
+ help = ""
+ name = o.name
+
+ if o.help ~= nil then
+ help = bmx6json.text2html(o.help)
+ end
+
+ if o.syntax ~= nil then
+ help = help .. " Syntax: " .. bmx6json.text2html(o.syntax)
+ end
+
+ if o.def ~= nil then
+ help = help .. " Default: " .. o.def
+ end
+
+ value = general:option(Value,name,name,help)
+
+ end
+end
+
+function m.on_commit(self,map)
+ local err = sys.call('bmx6 -c --configReload > /tmp/bmx6-luci.err.tmp')
+ if err ~= 0 then
+ m.message = sys.exec("cat /tmp/bmx6-luci.err.tmp")
+ end
+end
+
+return m
+
diff --git a/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/cbi/bmx6/hna.lua b/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/cbi/bmx6/hna.lua
new file mode 100644
index 0000000..db98ae6
--- /dev/null
+++ b/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/cbi/bmx6/hna.lua
@@ -0,0 +1,47 @@
+--[[
+ Copyright (C) 2011 Pau Escrich
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+--]]
+
+local sys = require("luci.sys")
+
+m = Map("bmx6", "bmx6")
+
+local hna = m:section(TypedSection,"unicastHna","IPv6 HNA")
+hna.addremove = true
+hna.anonymous = true
+local hna_option = hna:option(Value,"unicastHna", "IPv6 Host Network Announcement. Syntax /")
+
+--function hna_option:validate(value)
+-- local err = sys.call('bmx6 -c --test -a ' .. value)
+-- if err ~= 0 then
+-- return nil
+-- end
+-- return value
+--end
+
+function m.on_commit(self,map)
+ local err = sys.call('bmx6 -c --configReload > /tmp/bmx6-luci.err.tmp')
+ if err ~= 0 then
+ m.message = sys.exec("cat /tmp/bmx6-luci.err.tmp")
+ end
+end
+
+return m
+
diff --git a/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/cbi/bmx6/interfaces.lua b/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/cbi/bmx6/interfaces.lua
new file mode 100644
index 0000000..fb1261b
--- /dev/null
+++ b/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/cbi/bmx6/interfaces.lua
@@ -0,0 +1,77 @@
+--[[
+ Copyright (C) 2011 Pau Escrich
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+--]]
+
+local sys = require("luci.sys")
+local bmx6json = require("luci.model.bmx6json")
+local m = Map("bmx6", "bmx6")
+
+local eth_int = sys.net.devices()
+local interfaces = m:section(TypedSection,"dev","Devices","")
+interfaces.addremove = true
+interfaces.anonymous = true
+
+local intlv = interfaces:option(ListValue,"dev","Device")
+
+for _,i in ipairs(eth_int) do
+ intlv:value(i,i)
+end
+
+-- Getting json and looking for device section
+local json = bmx6json.get("options")
+
+if json == nil or json.OPTIONS == nil then
+ m.message = "bmx6-json plugin is not running or some mistake in luci-bmx6 configuration, check /etc/config/luci-bmx6"
+ json = {}
+else
+ json = json.OPTIONS
+end
+
+local dev = {}
+for _,j in ipairs(json) do
+ if j.name == "dev" and j.CHILD_OPTIONS ~= nil then
+ dev = j.CHILD_OPTIONS
+ break
+ end
+end
+
+local help = ""
+local name = ""
+
+for _,o in ipairs(dev) do
+ if o.name ~= nil then
+ help = ""
+ name = o.name
+ if o.help ~= nil then
+ help = bmx6json.text2html(o.help)
+ end
+
+ if o.syntax ~= nil then
+ help = help .. " Syntax: " .. bmx6json.text2html(o.syntax)
+ end
+
+ value = interfaces:option(Value,name,name,help)
+ value.optional = true
+ end
+end
+
+
+return m
+
diff --git a/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/cbi/bmx6/main.lua b/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/cbi/bmx6/main.lua
new file mode 100644
index 0000000..8ff3520
--- /dev/null
+++ b/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/cbi/bmx6/main.lua
@@ -0,0 +1,105 @@
+--[[
+ Copyright (C) 2011 Pau Escrich
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+--]]
+
+local sys = require("luci.sys")
+local bmx6json = require("luci.model.bmx6json")
+
+m = Map("bmx6", "bmx6")
+
+-- Getting json and Checking if bmx6-json is avaiable
+local options = bmx6json.get("options")
+if options == nil or options.OPTIONS == nil then
+ m.message = "bmx6-json plugin is not running or some mistake in luci-bmx6 configuration, check /etc/config/luci-bmx6"
+ return m
+else
+ options = options.OPTIONS
+end
+
+-- Getting a list of interfaces
+local eth_int = luci.sys.net.devices()
+
+local tunDev = m:section(TypedSection,"tunDev",translate("Tunnel device"),translate("Define incoming ipip tunnel interface name"))
+tunDev.addremove = true
+tunDev.anonymous = true
+tunDev:option(Value,"tunDev",translate("Name"),translate("Name for the tunnel network device"))
+tunDev:option(Value,"tun4Address", translate("IPv4 address/length"),translate("Specify default IPv4 tunnel address and announced range (ex. 10.1.2.3/24)"))
+tunDev:option(Value,"tun6Address", translate("IPv6 address/length"),translate("Specify default IPv6 tunnel address and announced range (ex. 2012:0:0:123:0:0:0:1/64)"))
+
+-- IP section
+local ipV = m:section(NamedSection,"ipVersion","ipVersion",translate("Miscellaneous IP options"))
+ipV.addremove = false
+local lipv = ipV:option(ListValue,"ipVersion",translate("IP version"))
+lipv:value("6","6")
+lipv.default = "6"
+
+-- rest of ip options are optional, getting them from json
+local ipoptions = {}
+for _,o in ipairs(options) do
+ if o.name == "ipVersion" and o.CHILD_OPTIONS ~= nil then
+ ipoptions = o.CHILD_OPTIONS
+ break
+ end
+end
+
+local help = ""
+local name = ""
+local value = nil
+
+for _,o in ipairs(ipoptions) do
+ if o.name ~= nil then
+ help = ""
+ name = o.name
+ if o.help ~= nil then
+ help = bmx6json.text2html(o.help)
+ end
+
+ if o.syntax ~= nil then
+ help = help .. " Syntax: " .. bmx6json.text2html(o.syntax)
+ end
+
+ if o.def ~= nil then
+ help = help .. " Default: " .. bmx6json.text2html(o.def)
+ end
+
+ value = ipV:option(Value,name,name,help)
+ value.optional = true
+ end
+end
+
+-- Interfaces section
+local interfaces = m:section(TypedSection,"dev",translate("Devices"),translate("Network devices to mesh with"))
+interfaces.addremove = true
+interfaces.anonymous = true
+local intlv = interfaces:option(ListValue,"dev",translate("Device"))
+
+for _,i in ipairs(eth_int) do
+ intlv:value(i,i)
+end
+
+function m.on_commit(self,map)
+ local err = sys.call('bmx6 -c --configReload > /tmp/bmx6-luci.err.tmp')
+ if err ~= 0 then
+ m.message = sys.exec("cat /tmp/bmx6-luci.err.tmp")
+ end
+end
+
+return m
+
diff --git a/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/cbi/bmx6/plugins.lua b/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/cbi/bmx6/plugins.lua
new file mode 100644
index 0000000..518864e
--- /dev/null
+++ b/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/cbi/bmx6/plugins.lua
@@ -0,0 +1,50 @@
+--[[
+ Copyright (C) 2011 Pau Escrich
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+--]]
+local sys = require("luci.sys")
+
+m = Map("bmx6", "bmx6")
+plugins_dir = {"/usr/lib/","/var/lib","/lib"}
+
+plugin = m:section(TypedSection,"plugin","Plugin")
+plugin.addremove = true
+plugin.anonymous = true
+plv = plugin:option(ListValue,"plugin", "Plugin")
+
+for _,d in ipairs(plugins_dir) do
+ pl = luci.sys.exec("cd "..d..";ls bmx6_*")
+ if #pl > 6 then
+ for _,v in ipairs(luci.util.split(pl,"\n")) do
+ plv:value(v,v)
+ end
+ end
+end
+
+
+function m.on_commit(self,map)
+ local err = sys.call('/etc/init.d/bmx6 restart')
+ if err ~= 0 then
+ m.message = sys.exec("Cannot restart bmx6")
+ end
+end
+
+
+return m
+
diff --git a/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/cbi/bmx6/tunnels.lua b/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/cbi/bmx6/tunnels.lua
new file mode 100644
index 0000000..92b14fc
--- /dev/null
+++ b/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/cbi/bmx6/tunnels.lua
@@ -0,0 +1,70 @@
+--[[
+ Copyright (C) 2011 Pau Escrich
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+--]]
+
+local sys = require("luci.sys")
+local bmx6json = require("luci.model.bmx6json")
+
+m = Map("bmx6", "bmx6")
+
+-- tunOut
+local tunnelsOut = m:section(TypedSection,"tunOut",translate("Networks to fetch"),translate("Gateways announcements to fetch"))
+tunnelsOut.addremove = true
+tunnelsOut.anonymous = true
+tunnelsOut:option(Value,"tunOut","Name")
+tunnelsOut:option(Value,"network", translate("Network to fetch"))
+
+local tunoptions = bmx6json.getOptions("tunOut")
+local _,o
+for _,o in ipairs(tunoptions) do
+ if o.name ~= nil and o.name ~= "network" then
+ help = bmx6json.getHtmlHelp(o)
+ value = tunnelsOut:option(Value,o.name,o.name,help)
+ value.optional = true
+ end
+end
+
+
+-- tunOut
+local tunnelsIn = m:section(TypedSection,"tunIn",translate("Networks to offer"),translate("Gateways to announce in the network"))
+tunnelsIn.addremove = true
+tunnelsIn.anonymous = true
+tunnelsIn:option(Value,"tunIn","Name")
+tunnelsIn:option(Value,"network", translate("Network to offer"))
+
+local tunInoptions = bmx6json.getOptions("tunIn")
+local _,o
+for _,o in ipairs(tunInoptions) do
+ if o.name ~= nil and o.name ~= "network" then
+ help = bmx6json.getHtmlHelp(o)
+ value = tunnelsIn:option(Value,o.name,o.name,help)
+ value.optional = true
+ end
+end
+
+function m.on_commit(self,map)
+ --Not working. If test returns error the changes are still commited
+ local msg = bmx6json.testandreload()
+ if msg ~= nil then
+ m.message = msg
+ end
+end
+
+return m
diff --git a/luci-app-bmx6/bmx6/usr/lib/lua/luci/view/admin_status/index/neighbours_simple.htm b/luci-app-bmx6/bmx6/usr/lib/lua/luci/view/admin_status/index/neighbours_simple.htm
new file mode 100644
index 0000000..97d6e0e
--- /dev/null
+++ b/luci-app-bmx6/bmx6/usr/lib/lua/luci/view/admin_status/index/neighbours_simple.htm
@@ -0,0 +1,108 @@
+
+
+
This is sms a chat where all bmx6 nodes can participate. The data is replayed using routing packets, so there is a limit of 2040 bytes. Use it only to send short messages.
+
Each participant can only send one sms at same time.
+
+
+Received SMS
+
+
+<% for orig,sms in pairs(chat) do %>
+ <%=orig%>:<%=sms%>
+<% end %>
+
+
+<%+footer%>
+
diff --git a/luci-app-bmx6/bmx6/usr/lib/lua/luci/view/bmx6/graph.htm b/luci-app-bmx6/bmx6/usr/lib/lua/luci/view/bmx6/graph.htm
new file mode 100644
index 0000000..0655302
--- /dev/null
+++ b/luci-app-bmx6/bmx6/usr/lib/lua/luci/view/bmx6/graph.htm
@@ -0,0 +1,49 @@
+<%#
+Copyright (C) 2011 Pau Escrich
+Contributors Jo-Philip
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+The full GNU General Public License is included in this distribution in
+the file called "COPYING".
+-%>
+
+<%
+ luci.http.prepare_content("text/html")
+
+ local location = { unpack(luci.dispatcher.context.path) }
+ location[#location] = "topology"
+%>
+
+<%+header%>
+
+
+
+
Rate (rx/tx):
+ <% if l.rxRate+l.txRate < 120 then %>
+
+ <% else %>
+
+ <% end %>
+ <%=l.rxRate%>/<%=l.txRate%>
+
+
+
Routes: <%=l.routes%>
+
+
+
+
+
+<% end %>
+
+<% end %>
+
+
+
+
+<%+footer%>
diff --git a/luci-app-bmx6/bmx6/usr/lib/lua/luci/view/bmx6/nodes_j.htm b/luci-app-bmx6/bmx6/usr/lib/lua/luci/view/bmx6/nodes_j.htm
new file mode 100644
index 0000000..8ebd5ee
--- /dev/null
+++ b/luci-app-bmx6/bmx6/usr/lib/lua/luci/view/bmx6/nodes_j.htm
@@ -0,0 +1,204 @@
+<%#
+ Copyright (C) 2011 Pau Escrich
+ Contributors Lluis Esquerda
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+-%>
+
+<%+header%>
+
+
+
+
+
+
+
+
+
+a mesh routing protocol for Linux devices.
+Visit bmx6.net for more info.
+
+
+
+
+
status
+
+
+
+
+
+
+
+<%+footer%>
+
diff --git a/luci-app-bmx6/bmx6/usr/lib/lua/luci/view/bmx6/tunnels_j.htm b/luci-app-bmx6/bmx6/usr/lib/lua/luci/view/bmx6/tunnels_j.htm
new file mode 100644
index 0000000..92b22a9
--- /dev/null
+++ b/luci-app-bmx6/bmx6/usr/lib/lua/luci/view/bmx6/tunnels_j.htm
@@ -0,0 +1,106 @@
+<%#
+ Copyright (C) 2011 Pau Escrich
+ Contributors Lluis Esquerda
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+-%>
+
+
+<%+header%>
+
+
+
+
+
+
+
+
Gateways tunnel announcements
+
+
+
+
+
+
+
+<%+footer%>
+
diff --git a/luci-app-bmx6/bmx6/www/cgi-bin/bmx6-info b/luci-app-bmx6/bmx6/www/cgi-bin/bmx6-info
new file mode 100755
index 0000000..6518c8d
--- /dev/null
+++ b/luci-app-bmx6/bmx6/www/cgi-bin/bmx6-info
@@ -0,0 +1,118 @@
+#!/bin/sh
+# This script gives information about bmx6
+# Can be executed from a linux shell: ./bmx6-info -s links
+# Or from web interfae (with cgi enabled): http://host/cgi-bin/bmx6-info?links
+# Special methods are tagged with '$', like $myself or $neighbours: http://host/cgi-bin/bmx6-info?$myself
+# When '$' is not used, raw bmx6 information from the filesystem is returned (/var/runb/bmx6/json/)
+
+BMX6_DIR="$(uci get bmx6.general.runtimeDir 2>/dev/null)" || BMX6_DIR="/var/run/bmx6/json"
+
+#Checking if shell mode or cgi-bin mode
+if [ "$1" == "-s" ]; then
+ QUERY="$2"
+else
+ QUERY="${QUERY_STRING%%=*}"
+ QUERY="${QUERY%%\?*}"
+ QUERY="${QUERY%%\&*}"
+ echo "Content-type: application/json"
+ echo ""
+fi
+
+check_path() {
+ [ -d "$1" ] && path=$(cd $1; pwd)
+ [ -f "$1" ] && path=$(cd $1/..; pwd)
+ [ $(echo "$path" | grep -c "^$BMX6_DIR") -ne 1 ] && exit 1
+}
+
+print_query() {
+ # If the query is a directory
+ [ -d "$BMX6_DIR/$1" ] &&
+ {
+ # If /all has not been specified
+ [ -z "$QALL" ] &&
+ {
+ total=$(ls $BMX6_DIR/$1 | wc -w)
+ i=1
+ echo -n "{ \"$1\": [ "
+ for f in $(ls $BMX6_DIR/$1); do
+ echo -n "{ \"name\": \"$f\" }"
+ [ $i -lt $total ] && echo -n ','
+ i=$(( $i + 1 ))
+ done
+ echo -n " ] }"
+
+ # If /all has been specified, printing all the files together
+ } || {
+ comma=""
+ echo -n "[ "
+ for entry in "$BMX6_DIR/$1/"*; do
+ [ -f "$entry" ] &&
+ {
+ ${comma:+echo -n "$comma"}
+ tr -d '\n' < "$entry"
+ comma=","
+ }
+ done
+ echo -n " ]"
+ }
+ }
+ # If the query is a file, just printing the file
+ [ -f "$BMX6_DIR/$1" ] && cat "$BMX6_DIR/$1";
+}
+
+if [ "${QUERY##*/}" == "all" ]; then
+ QUERY="${QUERY%/all}"
+ QALL=1
+fi
+
+if [ "$QUERY" == '$myself' ]; then
+ hostname="$(cat /proc/sys/kernel/hostname)"
+ ip6="$(bmx6 -c show=status | grep ^BMX | awk '{print $5}')"
+ ip4="$(bmx6 -c show=status | grep ^BMX | awk '{print $6}')"
+ cidr6=$(lua -l luci.ip -e "ip=luci.ip.new(\"$ip6\"); print(ip:network():string()..'/'..ip:prefix())")
+ cidr4=$(lua -l luci.ip -e "ip=luci.ip.new(\"$ip4\"); print(ip:network():string()..'/'..ip:prefix())")
+ echo -n "{\"myself\":{\"hostname\":\"$hostname\",\"ip6\":\"$ip6\",\"ip4\":\"$ip4\",\"net6\":\"$cidr6\",\"net4\":\"$cidr4\"}}"
+ exit 0
+fi
+
+if [ "$QUERY" == '$info' ]; then
+ echo -n '{ "info": [ '
+ print_query status
+ echo -n ","
+ print_query interfaces
+ echo -n "] }"
+ exit 0
+fi
+
+if [ "$QUERY" == '$neighbours' ]; then
+ QALL=1
+ echo -n '{ "neighbours": [ '
+ echo -n '{ "originators": '
+ print_query originators
+ echo -n '}, '
+ echo -n '{ "descriptions": '
+ print_query descriptions
+ echo -n "} ] }"
+ exit 0
+fi
+
+if [ "$QUERY" == '$tunnels' ]; then
+ bmx6 -c --jshow tunnels /r=0
+ exit 0
+fi
+
+if [ "$QUERY" == "" ]; then
+ echo -n '{ "queries": ['
+ echo -n '{ "name": "$myself", "info": "basic network information of self node" },'
+ echo -n '{ "name": "$info", "info": "full network and device information of self node" },'
+ echo -n '{ "name": "$tunnels", "info": "accnouncements (tunnels) published by the mesh network" },'
+ echo -n '{ "name": "$neighbours", "info": "list of all my neighbours and their information" },'
+ echo -n '{ "name": "/", "info": "raw bmx6 json API" }]}'
+ exit 0
+fi
+
+check_path "$BMX6_DIR/$QUERY"
+print_query $QUERY
+
+#ls -1F "$BMX6_DIR"
+exit 0
diff --git a/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/bmx6logo.png b/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/bmx6logo.png
new file mode 100644
index 0000000..12f7526
Binary files /dev/null and b/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/bmx6logo.png differ
diff --git a/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/js/bmx6-graph.js b/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/js/bmx6-graph.js
new file mode 100644
index 0000000..80233ff
--- /dev/null
+++ b/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/js/bmx6-graph.js
@@ -0,0 +1,234 @@
+var graph, canvas, layouter, renderer, divwait, nodes, announcements, nodesIndex, palette, localInfo;
+document.addEventListener( "DOMContentLoaded", init, false);
+
+/**
+ * Returns an index of nodes by name
+ */
+function createNodeIndex(nodes) {
+ var inode, index = {};
+
+ for (inode in nodes)
+ index[nodes[inode].name] = nodes[inode];
+
+ return index;
+}
+
+/**
+ * Updates to have announcements in nodes list
+ */
+function processNodeAnnouncements(nodes, announcements) {
+ var iannouncement, remoteNode, announcement;
+ nodesIndex = createNodeIndex(nodes);
+
+ for(iannouncement in announcements) {
+ announcement = announcements[iannouncement];
+ if (announcement.remoteName == '---' ) continue;
+ if (!( announcement.remoteName in nodesIndex )) {
+ newNode = {
+ name: announcement.remoteName,
+ links: []
+ };
+ nodes.push(newNode);
+ nodesIndex[newNode.name] = newNode;
+ };
+
+ remoteNode = nodesIndex[announcement.remoteName];
+ if (!( 'announcements' in remoteNode )) remoteNode.announcements = [];
+ remoteNode.announcements.push(announcement);
+ };
+}
+
+function init() {
+ palette = generatePalette(200);
+
+ graph = new Graph();
+ canvas = document.getElementById('canvas');
+ layouter = new Graph.Layout.Spring(graph);
+ renderer = new Graph.Renderer.Raphael(canvas.id, graph, canvas.offsetWidth, canvas.offsetHeight);
+
+ divwait = document.getElementById("wait");
+
+ XHR.get('/cgi-bin/luci/status/bmx6/topology', null, function(nodesRequest, nodesData) {
+ nodes = nodesData;
+
+ XHR.get('/cgi-bin/bmx6-info?$myself&', null, function(myselfRequest, myselfData) {
+ if (myselfData)
+ localAnnouncements = [
+ {remoteName: myselfData.myself.hostname, advNet: myselfData.myself.net4},
+ {remoteName: myselfData.myself.hostname, advNet: myselfData.myself.net6}
+ ];
+
+ XHR.get('/cgi-bin/bmx6-info?$tunnels=&', null, function(tunnelsRequest, tunnelsData) {
+ var iAnnouncement;
+
+ announcements = tunnelsData.tunnels;
+ for(iAnnouncement in localAnnouncements) {
+ announcements.push(localAnnouncements[iAnnouncement])
+ };
+
+ processNodeAnnouncements(nodes, announcements);
+
+ divwait.parentNode.removeChild(divwait);
+ draw(nodes);
+ });
+ });
+ });
+}
+
+function hashCode(str) {
+ var hash = 0;
+ if (str.length == 0) return hash;
+ for (i = 0; i < str.length; i++) {
+ char = str.charCodeAt(i);
+ hash = ((hash<<5)-hash)+char;
+ hash = hash & hash; // Convert to 32bit integer
+ }
+ return hash;
+}
+
+function generatePalette(size) {
+ var i, arr = [];
+ Raphael.getColor(); // just to remove the grey one
+ for(i = 0; i < size; i++) {
+ arr.push(Raphael.getColor())
+ }
+
+ return arr;
+}
+
+function getFillFromHash(hash) {
+ return palette[Math.abs(hash % palette.length)];
+}
+
+function hashAnnouncementsNames(announcementsNames) {
+ return hashCode(announcementsNames.sort().join('-'));
+}
+
+function getNodeAnnouncements(networkNode) {
+ return networkNode.announcements;
+}
+
+function nodeRenderer(raphael, node) {
+ var nodeFill, renderedNode, options;
+ options = {
+ 'fill': 'announcements' in node.networkNode ? getFillFromHash(
+ hashAnnouncementsNames(
+ getNodeAnnouncements(node.networkNode).map(function(ann) {return ann.advNet;})
+ )
+ ) : '#bfbfbf',
+ 'stroke-width': 1,
+
+ };
+
+ renderedNode = raphael.set();
+
+ renderedNode.push(raphael.ellipse(node.point[0], node.point[1], 30, 20).attr({"fill": options['fill'], "stroke-width": options['stroke-width']}));
+ renderedNode.push(raphael.text(node.point[0], node.point[1] + 30, node.networkNode.name).attr({}));
+
+ renderedNode.items.forEach(function(el) {
+ var announcements, tooltip = raphael.set();
+ tooltip.push(raphael.rect(-60, -60, 120, 60).attr({"fill": "#fec", "stroke-width": 1, r : "9px"}));
+
+ announcements = getNodeAnnouncements(node.networkNode);
+ if (announcements) {
+
+ announcements = announcements.map(function(ann) {return ann.advNet});
+ tooltip.push(raphael.text(0, -40, 'announcements\n' + announcements.join('\n')).attr({}));
+ };
+
+ el.tooltip(tooltip);
+ });
+
+ return renderedNode;
+}
+
+function genericNodeRenderer(raphael, node) {
+ var renderedNode;
+
+ renderedNode = raphael.set();
+
+ renderedNode.push(raphael.ellipse(node.point[0], node.point[1], 30, 20).attr({"fill": '#bfbfbf', "stroke-width": 1}));
+ renderedNode.push(raphael.text(node.point[0], node.point[1] + 30, node.networkNode.name).attr({}));
+
+ return renderedNode;
+}
+
+function redraw() {
+ layouter.layout();
+ renderer.draw();
+}
+
+function interpolateColor(minColor,maxColor,maxDepth,depth){
+
+ function d2h(d) {return d.toString(16);}
+ function h2d(h) {return parseInt(h,16);}
+
+ if(depth == 0){
+ return minColor;
+ }
+ if(depth == maxDepth){
+ return maxColor;
+ }
+
+ var color = "#";
+
+ for(var i=1; i <= 6; i+=2){
+ var minVal = new Number(h2d(minColor.substr(i,2)));
+ var maxVal = new Number(h2d(maxColor.substr(i,2)));
+ var nVal = minVal + (maxVal-minVal) * (depth/maxDepth);
+ var val = d2h(Math.floor(nVal));
+ while(val.length < 2){
+ val = "0"+val;
+ }
+ color += val;
+ }
+ return color;
+}
+function draw(nodes) {
+ var node, neighbourNode, seenKey, rxRate, txRate, seen, i, j, currentName, linkQuality;
+
+ seen = { };
+
+ for (i = 0; i < (nodes.length); i++) {
+ node = nodes[i];
+ graph.addNode(node.name, {
+ networkNode: node,
+ render: nodeRenderer
+ });
+ };
+
+ for (i = 0; i < (nodes.length); i++) {
+ node = nodes[i];
+
+ if (! node.name) continue;
+
+ currentName = node.name;
+
+ for (j = 0; j < (node.links.length); j++) {
+ neighbourNode = node.links[j];
+
+ graph.addNode(neighbourNode.name, {render: genericNodeRenderer, networkNode: neighbourNode});
+
+ seenKey = (node.name < neighbourNode.name) ? node.name + '|' + neighbourNode.name : neighbourNode.name + '|' + node.name;
+
+ rxRate = neighbourNode.rxRate;
+ txRate = neighbourNode.txRate;
+
+ if (!seen[seenKey] && rxRate > 0 && txRate > 0) {
+ linkQuality = ( rxRate + txRate ) / 2;
+
+ graph.addEdge(node.name, neighbourNode.name, {
+ 'label': rxRate + '/' + txRate,
+ 'directed': false,
+ 'stroke': interpolateColor('FF0000','00FF00', 5, 5 * ( linkQuality - 1 )/100),
+ 'fill': interpolateColor('FF0000','00FF00', 5, 5 * ( linkQuality - 1 )/100),
+ 'label-style': { 'font-size': 8 }
+ });
+
+ seen[seenKey] = true;
+ }
+ }
+ }
+
+ redraw();
+}
diff --git a/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/js/polling.js b/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/js/polling.js
new file mode 100644
index 0000000..8f81443
--- /dev/null
+++ b/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/js/polling.js
@@ -0,0 +1,81 @@
+/*
+ Copyright (C) 2011 Pau Escrich
+ Contributors Lluis Esquerda
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+*/
+
+
+/*
+ Table pooler is a function to easy call XHR poller.
+
+ new TablePooler(5,"/cgi-bin/bmx6-info", {'status':''}, "status_table", function(st){
+ var table = Array()
+ table.push(st.first,st.second)
+ return table
+ }
+ Parameters are:
+ polling_time: time between pollings
+ json_url: the json url to fetch the data
+ json_call: the json call
+ output_table_id: the table where javascript will put the data
+ callback_function: the function that will be executed each polling_time
+
+ The callback_function must return an array of arrays (matrix).
+ In the code st is the data obtained from the json call
+*/
+
+ function TablePooler (time, jsonurl, getparams, table_id, callback) {
+ this.table = document.getElementById(table_id);
+ this.callback = callback;
+ this.jsonurl = jsonurl;
+ this.getparams = getparams;
+ this.time = time;
+
+ this.clear = function(){
+ /* clear all rows */
+ while( this.table.rows.length > 1 ) this.table.deleteRow(1);
+ }
+ this.start = function(){
+ XHR.poll(this.time, this.jsonurl, this.getparams, function(x, st){
+ var data = this.callback(st);
+ var content, tr, td;
+ this.clear();
+ for (var i = 0; i < data.length; i++){
+ tr = this.table.insertRow(-1);
+ tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
+
+ for (var j = 0; j < data[i].length; j++){
+ td = tr.insertCell(-1);
+ if (data[i][j].length == 2) {
+ td.colSpan = data[i][j][1];
+ content = data[i][j][0];
+ }
+ else content = data[i][j];
+ td.innerHTML = content;
+ }
+ }
+ }.bind(this));
+ }
+
+
+ this.start();
+ }
+
+
+
diff --git a/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/link.png b/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/link.png
new file mode 100644
index 0000000..58977ff
Binary files /dev/null and b/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/link.png differ
diff --git a/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/style.css b/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/style.css
new file mode 100644
index 0000000..d8191a7
--- /dev/null
+++ b/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/style.css
@@ -0,0 +1,22 @@
+ table {
+ width:90%;
+ border-top:1px solid #e5eaf8;
+ border-right:1px solid #e5eaf8;
+ margin:1em auto;
+ border-collapse:collapse;
+ }
+
+ td {
+ color:#678197;
+ border-bottom:1px solid #e6eff8;
+ border-left:1px solid #e6eff8;
+ padding:.3em 1em;
+ text-align:center;
+ }
+ th {
+ background:#f4f9fe;
+ text-align:center;
+ font:bold 1.2em/2em Century Gothic,Trebuchet MS,Arial,Helvetica,sans-serif;
+ color:#66a3d3;
+ }
+
diff --git a/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/wifi.png b/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/wifi.png
new file mode 100644
index 0000000..4195b08
Binary files /dev/null and b/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/wifi.png differ
diff --git a/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/world.png b/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/world.png
new file mode 100644
index 0000000..29b53c9
Binary files /dev/null and b/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/world.png differ
diff --git a/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/world_small.png b/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/world_small.png
new file mode 100644
index 0000000..f5f3105
Binary files /dev/null and b/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/world_small.png differ
diff --git a/luci-app-bmx6/dracula/dracula_graffle.js b/luci-app-bmx6/dracula/dracula_graffle.js
new file mode 100644
index 0000000..9832727
--- /dev/null
+++ b/luci-app-bmx6/dracula/dracula_graffle.js
@@ -0,0 +1 @@
+Raphael.fn.connection=function(a,b,c){var d=this,e={draw:function(){for(var f=a.getBBox(),g=b.getBBox(),h=0,i=0,j=[{x:f.x+f.width/2,y:f.y-h},{x:f.x+f.width/2,y:f.y+f.height+h},{x:f.x-h,y:f.y+f.height/2},{x:f.x+f.width+h,y:f.y+f.height/2},{x:g.x+g.width/2,y:g.y-i},{x:g.x+g.width/2,y:g.y+g.height+i},{x:g.x-i,y:g.y+g.height/2},{x:g.x+g.width+i,y:g.y+g.height/2}],k={},l=[],m=0;m<4;m++)for(var n=4;n<8;n++){var o=Math.abs(j[m].x-j[n].x),p=Math.abs(j[m].y-j[n].y);(m==n-4||(3!=m&&6!=n||j[m].xj[n].x)&&(0!=m&&5!=n||j[m].y>j[n].y)&&(1!=m&&4!=n||j[m].ye.width-20?c-e.width+20:0),g=a.clientY-(d<20?d-20:d>e.height-20?d-e.height+20:0);e.isDrag.set.translate(f-Math.round(e.isDrag.dx),g-Math.round(e.isDrag.dy));for(var h in e.graph.edges)e.graph.edges[h].connection&&e.graph.edges[h].connection.draw();e.isDrag.dx=f,e.isDrag.dy=g}},f.onmouseup=function(){e.isDrag&&e.isDrag.set.animate({"fill-opacity":.6},500),e.isDrag=!1},this.draw()},Graph.Renderer.Raphael.prototype={translate:function(a){return[(a[0]-this.graph.layoutMinX)*this.factorX+this.radius,(a[1]-this.graph.layoutMinY)*this.factorY+this.radius]},rotate:function(a,b,c){var d=b*Math.cos(c),e=b*Math.sin(c);return[a[0]+d,a[1]+e]},draw:function(){this.factorX=(this.width-2*this.radius)/(this.graph.layoutMaxX-this.graph.layoutMinX),this.factorY=(this.height-2*this.radius)/(this.graph.layoutMaxY-this.graph.layoutMinY);for(a in this.graph.nodes)this.drawNode(this.graph.nodes[a]);for(var a=0;ab&&(b=e),ed&&(d=f),fk&&(i=k),i<-k&&(i=-k),j>k&&(j=k),j<-k&&(j=-k),h.layoutPosX+=i,h.layoutPosY+=j,h.layoutForceX=0,h.layoutForceY=0}},layoutRepulsive:function(a,b){if("undefined"!=typeof a&&"undefined"!=typeof b){var c=b.layoutPosX-a.layoutPosX,d=b.layoutPosY-a.layoutPosY,e=c*c+d*d;if(e<.01){c=.1*Math.random()+.1,d=.1*Math.random()+.1;var e=c*c+d*d}var f=Math.sqrt(e);if(fthis.maxRepulsiveForceDistance&&(g=this.maxRepulsiveForceDistance,f=g*g);var h=(f-this.k*this.k)/this.k;void 0==a.attraction&&(a.attraction=1),h*=.5*Math.log(a.attraction)+1,c.layoutForceX-=h*d/g,c.layoutForceY-=h*e/g,b.layoutForceX+=h*d/g,b.layoutForceY+=h*e/g}},Graph.Layout.Ordered=function(a,b){this.graph=a,this.order=b,this.layout()},Graph.Layout.Ordered.prototype={layout:function(){this.layoutPrepare(),this.layoutCalcBounds()},layoutPrepare:function(a){for(i in this.graph.nodes){var b=this.graph.nodes[i];b.layoutPosX=0,b.layoutPosY=0}var c=0;for(i in this.order){var b=this.order[i];b.layoutPosX=c,b.layoutPosY=Math.random(),c++}},layoutCalcBounds:function(){var a=1/0,b=-(1/0),c=1/0,d=-(1/0);for(i in this.graph.nodes){var e=this.graph.nodes[i].layoutPosX,f=this.graph.nodes[i].layoutPosY;e>b&&(b=e),ed&&(d=f),f
This is sms a chat where all bmx6 nodes can participate. The data is replayed using routing packets, so there is a limit of 2040 bytes. Use it only to send short messages.
-
Each participant can only send one sms at same time.
-
-
-Received SMS
-
-
-<% for orig,sms in pairs(chat) do %>
- <%=orig%>:<%=sms%>
-<% end %>
-
-
-<%+footer%>
-
diff --git a/luci-app-bmx6/files/usr/lib/lua/luci/view/bmx6/graph.htm b/luci-app-bmx6/files/usr/lib/lua/luci/view/bmx6/graph.htm
deleted file mode 100644
index 580732e..0000000
--- a/luci-app-bmx6/files/usr/lib/lua/luci/view/bmx6/graph.htm
+++ /dev/null
@@ -1,49 +0,0 @@
-<%#
-Copyright (C) 2011 Pau Escrich
-Contributors Jo-Philip
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-The full GNU General Public License is included in this distribution in
-the file called "COPYING".
--%>
-
-<%
- luci.http.prepare_content("text/html")
-
- local location = { unpack(luci.dispatcher.context.path) }
- location[#location] = "topology"
-%>
-
-<%+header%>
-
-
-
-
Rate (rx/tx):
- <% if l.rxRate+l.txRate < 120 then %>
-
- <% else %>
-
- <% end %>
- <%=l.rxRate%>/<%=l.txRate%>
-
-
-
Routes: <%=l.routes%>
-
-
-
-
-
-<% end %>
-
-<% end %>
-
-
-
-
-<%+footer%>
diff --git a/luci-app-bmx6/files/usr/lib/lua/luci/view/bmx6/nodes_j.htm b/luci-app-bmx6/files/usr/lib/lua/luci/view/bmx6/nodes_j.htm
deleted file mode 100644
index 8ebd5ee..0000000
--- a/luci-app-bmx6/files/usr/lib/lua/luci/view/bmx6/nodes_j.htm
+++ /dev/null
@@ -1,204 +0,0 @@
-<%#
- Copyright (C) 2011 Pau Escrich
- Contributors Lluis Esquerda
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
- The full GNU General Public License is included in this distribution in
- the file called "COPYING".
--%>
-
-<%+header%>
-
-
-
-
-
-
-
-
-
-a mesh routing protocol for Linux devices.
-Visit bmx6.net for more info.
-
-
-
-
-
status
-
-
-
-
-
-
-
-<%+footer%>
-
diff --git a/luci-app-bmx6/files/usr/lib/lua/luci/view/bmx6/tunnels_j.htm b/luci-app-bmx6/files/usr/lib/lua/luci/view/bmx6/tunnels_j.htm
deleted file mode 100644
index 92b22a9..0000000
--- a/luci-app-bmx6/files/usr/lib/lua/luci/view/bmx6/tunnels_j.htm
+++ /dev/null
@@ -1,106 +0,0 @@
-<%#
- Copyright (C) 2011 Pau Escrich
- Contributors Lluis Esquerda
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
- The full GNU General Public License is included in this distribution in
- the file called "COPYING".
--%>
-
-
-<%+header%>
-
-
-
-
-
-
-
-
Gateways tunnel announcements
-
-
-
-
-
-
-
-<%+footer%>
-
diff --git a/luci-app-bmx6/files/www/cgi-bin/bmx6-info b/luci-app-bmx6/files/www/cgi-bin/bmx6-info
deleted file mode 100755
index 6518c8d..0000000
--- a/luci-app-bmx6/files/www/cgi-bin/bmx6-info
+++ /dev/null
@@ -1,118 +0,0 @@
-#!/bin/sh
-# This script gives information about bmx6
-# Can be executed from a linux shell: ./bmx6-info -s links
-# Or from web interfae (with cgi enabled): http://host/cgi-bin/bmx6-info?links
-# Special methods are tagged with '$', like $myself or $neighbours: http://host/cgi-bin/bmx6-info?$myself
-# When '$' is not used, raw bmx6 information from the filesystem is returned (/var/runb/bmx6/json/)
-
-BMX6_DIR="$(uci get bmx6.general.runtimeDir 2>/dev/null)" || BMX6_DIR="/var/run/bmx6/json"
-
-#Checking if shell mode or cgi-bin mode
-if [ "$1" == "-s" ]; then
- QUERY="$2"
-else
- QUERY="${QUERY_STRING%%=*}"
- QUERY="${QUERY%%\?*}"
- QUERY="${QUERY%%\&*}"
- echo "Content-type: application/json"
- echo ""
-fi
-
-check_path() {
- [ -d "$1" ] && path=$(cd $1; pwd)
- [ -f "$1" ] && path=$(cd $1/..; pwd)
- [ $(echo "$path" | grep -c "^$BMX6_DIR") -ne 1 ] && exit 1
-}
-
-print_query() {
- # If the query is a directory
- [ -d "$BMX6_DIR/$1" ] &&
- {
- # If /all has not been specified
- [ -z "$QALL" ] &&
- {
- total=$(ls $BMX6_DIR/$1 | wc -w)
- i=1
- echo -n "{ \"$1\": [ "
- for f in $(ls $BMX6_DIR/$1); do
- echo -n "{ \"name\": \"$f\" }"
- [ $i -lt $total ] && echo -n ','
- i=$(( $i + 1 ))
- done
- echo -n " ] }"
-
- # If /all has been specified, printing all the files together
- } || {
- comma=""
- echo -n "[ "
- for entry in "$BMX6_DIR/$1/"*; do
- [ -f "$entry" ] &&
- {
- ${comma:+echo -n "$comma"}
- tr -d '\n' < "$entry"
- comma=","
- }
- done
- echo -n " ]"
- }
- }
- # If the query is a file, just printing the file
- [ -f "$BMX6_DIR/$1" ] && cat "$BMX6_DIR/$1";
-}
-
-if [ "${QUERY##*/}" == "all" ]; then
- QUERY="${QUERY%/all}"
- QALL=1
-fi
-
-if [ "$QUERY" == '$myself' ]; then
- hostname="$(cat /proc/sys/kernel/hostname)"
- ip6="$(bmx6 -c show=status | grep ^BMX | awk '{print $5}')"
- ip4="$(bmx6 -c show=status | grep ^BMX | awk '{print $6}')"
- cidr6=$(lua -l luci.ip -e "ip=luci.ip.new(\"$ip6\"); print(ip:network():string()..'/'..ip:prefix())")
- cidr4=$(lua -l luci.ip -e "ip=luci.ip.new(\"$ip4\"); print(ip:network():string()..'/'..ip:prefix())")
- echo -n "{\"myself\":{\"hostname\":\"$hostname\",\"ip6\":\"$ip6\",\"ip4\":\"$ip4\",\"net6\":\"$cidr6\",\"net4\":\"$cidr4\"}}"
- exit 0
-fi
-
-if [ "$QUERY" == '$info' ]; then
- echo -n '{ "info": [ '
- print_query status
- echo -n ","
- print_query interfaces
- echo -n "] }"
- exit 0
-fi
-
-if [ "$QUERY" == '$neighbours' ]; then
- QALL=1
- echo -n '{ "neighbours": [ '
- echo -n '{ "originators": '
- print_query originators
- echo -n '}, '
- echo -n '{ "descriptions": '
- print_query descriptions
- echo -n "} ] }"
- exit 0
-fi
-
-if [ "$QUERY" == '$tunnels' ]; then
- bmx6 -c --jshow tunnels /r=0
- exit 0
-fi
-
-if [ "$QUERY" == "" ]; then
- echo -n '{ "queries": ['
- echo -n '{ "name": "$myself", "info": "basic network information of self node" },'
- echo -n '{ "name": "$info", "info": "full network and device information of self node" },'
- echo -n '{ "name": "$tunnels", "info": "accnouncements (tunnels) published by the mesh network" },'
- echo -n '{ "name": "$neighbours", "info": "list of all my neighbours and their information" },'
- echo -n '{ "name": "/", "info": "raw bmx6 json API" }]}'
- exit 0
-fi
-
-check_path "$BMX6_DIR/$QUERY"
-print_query $QUERY
-
-#ls -1F "$BMX6_DIR"
-exit 0
diff --git a/luci-app-bmx6/files/www/luci-static/resources/bmx6/bmx6logo.png b/luci-app-bmx6/files/www/luci-static/resources/bmx6/bmx6logo.png
deleted file mode 100644
index 12f7526..0000000
Binary files a/luci-app-bmx6/files/www/luci-static/resources/bmx6/bmx6logo.png and /dev/null differ
diff --git a/luci-app-bmx6/files/www/luci-static/resources/bmx6/js/Curry-1.0.1.js b/luci-app-bmx6/files/www/luci-static/resources/bmx6/js/Curry-1.0.1.js
deleted file mode 100644
index f5aa0f9..0000000
--- a/luci-app-bmx6/files/www/luci-static/resources/bmx6/js/Curry-1.0.1.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Curry - Function currying
- * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
- * Licensed under BSD (http://www.opensource.org/licenses/bsd-license.php)
- * Date: 10/4/2008
- *
- * @author Ariel Flesler
- * @version 1.0.1
- */
-
-function curry( fn ){
- return function(){
- var args = curry.args(arguments),
- master = arguments.callee,
- self = this;
-
- return args.length >= fn.length ? fn.apply(self,args) : function(){
- return master.apply( self, args.concat(curry.args(arguments)) );
- };
- };
-};
-
-curry.args = function( args ){
- return Array.prototype.slice.call(args);
-};
-
-Function.prototype.curry = function(){
- return curry(this);
-};
\ No newline at end of file
diff --git a/luci-app-bmx6/files/www/luci-static/resources/bmx6/js/bmx6-graph.js b/luci-app-bmx6/files/www/luci-static/resources/bmx6/js/bmx6-graph.js
deleted file mode 100644
index 80233ff..0000000
--- a/luci-app-bmx6/files/www/luci-static/resources/bmx6/js/bmx6-graph.js
+++ /dev/null
@@ -1,234 +0,0 @@
-var graph, canvas, layouter, renderer, divwait, nodes, announcements, nodesIndex, palette, localInfo;
-document.addEventListener( "DOMContentLoaded", init, false);
-
-/**
- * Returns an index of nodes by name
- */
-function createNodeIndex(nodes) {
- var inode, index = {};
-
- for (inode in nodes)
- index[nodes[inode].name] = nodes[inode];
-
- return index;
-}
-
-/**
- * Updates to have announcements in nodes list
- */
-function processNodeAnnouncements(nodes, announcements) {
- var iannouncement, remoteNode, announcement;
- nodesIndex = createNodeIndex(nodes);
-
- for(iannouncement in announcements) {
- announcement = announcements[iannouncement];
- if (announcement.remoteName == '---' ) continue;
- if (!( announcement.remoteName in nodesIndex )) {
- newNode = {
- name: announcement.remoteName,
- links: []
- };
- nodes.push(newNode);
- nodesIndex[newNode.name] = newNode;
- };
-
- remoteNode = nodesIndex[announcement.remoteName];
- if (!( 'announcements' in remoteNode )) remoteNode.announcements = [];
- remoteNode.announcements.push(announcement);
- };
-}
-
-function init() {
- palette = generatePalette(200);
-
- graph = new Graph();
- canvas = document.getElementById('canvas');
- layouter = new Graph.Layout.Spring(graph);
- renderer = new Graph.Renderer.Raphael(canvas.id, graph, canvas.offsetWidth, canvas.offsetHeight);
-
- divwait = document.getElementById("wait");
-
- XHR.get('/cgi-bin/luci/status/bmx6/topology', null, function(nodesRequest, nodesData) {
- nodes = nodesData;
-
- XHR.get('/cgi-bin/bmx6-info?$myself&', null, function(myselfRequest, myselfData) {
- if (myselfData)
- localAnnouncements = [
- {remoteName: myselfData.myself.hostname, advNet: myselfData.myself.net4},
- {remoteName: myselfData.myself.hostname, advNet: myselfData.myself.net6}
- ];
-
- XHR.get('/cgi-bin/bmx6-info?$tunnels=&', null, function(tunnelsRequest, tunnelsData) {
- var iAnnouncement;
-
- announcements = tunnelsData.tunnels;
- for(iAnnouncement in localAnnouncements) {
- announcements.push(localAnnouncements[iAnnouncement])
- };
-
- processNodeAnnouncements(nodes, announcements);
-
- divwait.parentNode.removeChild(divwait);
- draw(nodes);
- });
- });
- });
-}
-
-function hashCode(str) {
- var hash = 0;
- if (str.length == 0) return hash;
- for (i = 0; i < str.length; i++) {
- char = str.charCodeAt(i);
- hash = ((hash<<5)-hash)+char;
- hash = hash & hash; // Convert to 32bit integer
- }
- return hash;
-}
-
-function generatePalette(size) {
- var i, arr = [];
- Raphael.getColor(); // just to remove the grey one
- for(i = 0; i < size; i++) {
- arr.push(Raphael.getColor())
- }
-
- return arr;
-}
-
-function getFillFromHash(hash) {
- return palette[Math.abs(hash % palette.length)];
-}
-
-function hashAnnouncementsNames(announcementsNames) {
- return hashCode(announcementsNames.sort().join('-'));
-}
-
-function getNodeAnnouncements(networkNode) {
- return networkNode.announcements;
-}
-
-function nodeRenderer(raphael, node) {
- var nodeFill, renderedNode, options;
- options = {
- 'fill': 'announcements' in node.networkNode ? getFillFromHash(
- hashAnnouncementsNames(
- getNodeAnnouncements(node.networkNode).map(function(ann) {return ann.advNet;})
- )
- ) : '#bfbfbf',
- 'stroke-width': 1,
-
- };
-
- renderedNode = raphael.set();
-
- renderedNode.push(raphael.ellipse(node.point[0], node.point[1], 30, 20).attr({"fill": options['fill'], "stroke-width": options['stroke-width']}));
- renderedNode.push(raphael.text(node.point[0], node.point[1] + 30, node.networkNode.name).attr({}));
-
- renderedNode.items.forEach(function(el) {
- var announcements, tooltip = raphael.set();
- tooltip.push(raphael.rect(-60, -60, 120, 60).attr({"fill": "#fec", "stroke-width": 1, r : "9px"}));
-
- announcements = getNodeAnnouncements(node.networkNode);
- if (announcements) {
-
- announcements = announcements.map(function(ann) {return ann.advNet});
- tooltip.push(raphael.text(0, -40, 'announcements\n' + announcements.join('\n')).attr({}));
- };
-
- el.tooltip(tooltip);
- });
-
- return renderedNode;
-}
-
-function genericNodeRenderer(raphael, node) {
- var renderedNode;
-
- renderedNode = raphael.set();
-
- renderedNode.push(raphael.ellipse(node.point[0], node.point[1], 30, 20).attr({"fill": '#bfbfbf', "stroke-width": 1}));
- renderedNode.push(raphael.text(node.point[0], node.point[1] + 30, node.networkNode.name).attr({}));
-
- return renderedNode;
-}
-
-function redraw() {
- layouter.layout();
- renderer.draw();
-}
-
-function interpolateColor(minColor,maxColor,maxDepth,depth){
-
- function d2h(d) {return d.toString(16);}
- function h2d(h) {return parseInt(h,16);}
-
- if(depth == 0){
- return minColor;
- }
- if(depth == maxDepth){
- return maxColor;
- }
-
- var color = "#";
-
- for(var i=1; i <= 6; i+=2){
- var minVal = new Number(h2d(minColor.substr(i,2)));
- var maxVal = new Number(h2d(maxColor.substr(i,2)));
- var nVal = minVal + (maxVal-minVal) * (depth/maxDepth);
- var val = d2h(Math.floor(nVal));
- while(val.length < 2){
- val = "0"+val;
- }
- color += val;
- }
- return color;
-}
-function draw(nodes) {
- var node, neighbourNode, seenKey, rxRate, txRate, seen, i, j, currentName, linkQuality;
-
- seen = { };
-
- for (i = 0; i < (nodes.length); i++) {
- node = nodes[i];
- graph.addNode(node.name, {
- networkNode: node,
- render: nodeRenderer
- });
- };
-
- for (i = 0; i < (nodes.length); i++) {
- node = nodes[i];
-
- if (! node.name) continue;
-
- currentName = node.name;
-
- for (j = 0; j < (node.links.length); j++) {
- neighbourNode = node.links[j];
-
- graph.addNode(neighbourNode.name, {render: genericNodeRenderer, networkNode: neighbourNode});
-
- seenKey = (node.name < neighbourNode.name) ? node.name + '|' + neighbourNode.name : neighbourNode.name + '|' + node.name;
-
- rxRate = neighbourNode.rxRate;
- txRate = neighbourNode.txRate;
-
- if (!seen[seenKey] && rxRate > 0 && txRate > 0) {
- linkQuality = ( rxRate + txRate ) / 2;
-
- graph.addEdge(node.name, neighbourNode.name, {
- 'label': rxRate + '/' + txRate,
- 'directed': false,
- 'stroke': interpolateColor('FF0000','00FF00', 5, 5 * ( linkQuality - 1 )/100),
- 'fill': interpolateColor('FF0000','00FF00', 5, 5 * ( linkQuality - 1 )/100),
- 'label-style': { 'font-size': 8 }
- });
-
- seen[seenKey] = true;
- }
- }
- }
-
- redraw();
-}
diff --git a/luci-app-bmx6/files/www/luci-static/resources/bmx6/js/dracula_graffle.js b/luci-app-bmx6/files/www/luci-static/resources/bmx6/js/dracula_graffle.js
deleted file mode 100644
index ddf171d..0000000
--- a/luci-app-bmx6/files/www/luci-static/resources/bmx6/js/dracula_graffle.js
+++ /dev/null
@@ -1,106 +0,0 @@
-/**
- * Originally grabbed from the official RaphaelJS Documentation
- * http://raphaeljs.com/graffle.html
- * Adopted (arrows) and commented by Philipp Strathausen http://blog.ameisenbar.de
- * Licenced under the MIT licence.
- */
-
-/**
- * Usage:
- * connect two shapes
- * parameters:
- * source shape [or connection for redrawing],
- * target shape,
- * style with { fg : linecolor, bg : background color, directed: boolean }
- * returns:
- * connection { draw = function() }
- */
-Raphael.fn.connection = function (obj1, obj2, style) {
- var selfRef = this;
- /* create and return new connection */
- var edge = {/*
- from : obj1,
- to : obj2,
- style : style,*/
- draw : function() {
- /* get bounding boxes of target and source */
- var bb1 = obj1.getBBox();
- var bb2 = obj2.getBBox();
- var off1 = 0;
- var off2 = 0;
- /* coordinates for potential connection coordinates from/to the objects */
- var p = [
- {x: bb1.x + bb1.width / 2, y: bb1.y - off1}, /* NORTH 1 */
- {x: bb1.x + bb1.width / 2, y: bb1.y + bb1.height + off1}, /* SOUTH 1 */
- {x: bb1.x - off1, y: bb1.y + bb1.height / 2}, /* WEST 1 */
- {x: bb1.x + bb1.width + off1, y: bb1.y + bb1.height / 2}, /* EAST 1 */
- {x: bb2.x + bb2.width / 2, y: bb2.y - off2}, /* NORTH 2 */
- {x: bb2.x + bb2.width / 2, y: bb2.y + bb2.height + off2}, /* SOUTH 2 */
- {x: bb2.x - off2, y: bb2.y + bb2.height / 2}, /* WEST 2 */
- {x: bb2.x + bb2.width + off2, y: bb2.y + bb2.height / 2} /* EAST 2 */
- ];
-
- /* distances between objects and according coordinates connection */
- var d = {}, dis = [];
-
- /*
- * find out the best connection coordinates by trying all possible ways
- */
- /* loop the first object's connection coordinates */
- for (var i = 0; i < 4; i++) {
- /* loop the seond object's connection coordinates */
- for (var j = 4; j < 8; j++) {
- var dx = Math.abs(p[i].x - p[j].x),
- dy = Math.abs(p[i].y - p[j].y);
- if ((i == j - 4) || (((i != 3 && j != 6) || p[i].x < p[j].x) && ((i != 2 && j != 7) || p[i].x > p[j].x) && ((i != 0 && j != 5) || p[i].y > p[j].y) && ((i != 1 && j != 4) || p[i].y < p[j].y))) {
- dis.push(dx + dy);
- d[dis[dis.length - 1].toFixed(3)] = [i, j];
- }
- }
- }
- var res = dis.length == 0 ? [0, 4] : d[Math.min.apply(Math, dis).toFixed(3)];
- /* bezier path */
- var x1 = p[res[0]].x,
- y1 = p[res[0]].y,
- x4 = p[res[1]].x,
- y4 = p[res[1]].y,
- dx = Math.max(Math.abs(x1 - x4) / 2, 10),
- dy = Math.max(Math.abs(y1 - y4) / 2, 10),
- x2 = [x1, x1, x1 - dx, x1 + dx][res[0]].toFixed(3),
- y2 = [y1 - dy, y1 + dy, y1, y1][res[0]].toFixed(3),
- x3 = [0, 0, 0, 0, x4, x4, x4 - dx, x4 + dx][res[1]].toFixed(3),
- y3 = [0, 0, 0, 0, y1 + dy, y1 - dy, y4, y4][res[1]].toFixed(3);
- /* assemble path and arrow */
- var path = ["M", x1.toFixed(3), y1.toFixed(3), "C", x2, y2, x3, y3, x4.toFixed(3), y4.toFixed(3)].join(",");
- /* arrow */
- if(style && style.directed) {
- /* magnitude, length of the last path vector */
- var mag = Math.sqrt((y4 - y3) * (y4 - y3) + (x4 - x3) * (x4 - x3));
- /* vector normalisation to specified length */
- var norm = function(x,l){return (-x*(l||5)/mag);};
- /* calculate array coordinates (two lines orthogonal to the path vector) */
- var arr = [
- {x:(norm(x4-x3)+norm(y4-y3)+x4).toFixed(3), y:(norm(y4-y3)+norm(x4-x3)+y4).toFixed(3)},
- {x:(norm(x4-x3)-norm(y4-y3)+x4).toFixed(3), y:(norm(y4-y3)-norm(x4-x3)+y4).toFixed(3)}
- ];
- path = path + ",M"+arr[0].x+","+arr[0].y+",L"+x4+","+y4+",L"+arr[1].x+","+arr[1].y;
- }
- /* function to be used for moving existent path(s), e.g. animate() or attr() */
- var move = "attr";
- /* applying path(s) */
- edge.fg && edge.fg[move]({path:path})
- || (edge.fg = selfRef.path(path).attr({stroke: style && style.stroke || "#000", fill: "none"}).toBack());
- edge.bg && edge.bg[move]({path:path})
- || style && style.fill && (edge.bg = style.fill.split && selfRef.path(path).attr({stroke: style.fill.split("|")[0], fill: "none", "stroke-width": style.fill.split("|")[1] || 3}).toBack());
- /* setting label */
- style && style.label
- && (edge.label && edge.label.attr({x:(x1+x4)/2, y:(y1+y4)/2})
- || (edge.label = selfRef.text((x1+x4)/2, (y1+y4)/2, style.label).attr({fill: "#000", "font-size": style["font-size"] || "12px"})));
- style && style.label && style["label-style"] && edge.label && edge.label.attr(style["label-style"]);
- style && style.callback && style.callback(edge);
- }
- }
- edge.draw();
- return edge;
-};
-//Raphael.prototype.set.prototype.dodo=function(){console.log("works");};
diff --git a/luci-app-bmx6/files/www/luci-static/resources/bmx6/js/dracula_graph.js b/luci-app-bmx6/files/www/luci-static/resources/bmx6/js/dracula_graph.js
deleted file mode 100644
index f3e43e1..0000000
--- a/luci-app-bmx6/files/www/luci-static/resources/bmx6/js/dracula_graph.js
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * Dracula Graph Layout and Drawing Framework 0.0.3alpha
- * (c) 2010 Philipp Strathausen , http://strathausen.eu
- * Contributions by Jake Stothard .
- *
- * based on the Graph JavaScript framework, version 0.0.1
- * (c) 2006 Aslak Hellesoy
- * (c) 2006 Dave Hoover
- *
- * Ported from Graph::Layouter::Spring in
- * http://search.cpan.org/~pasky/Graph-Layderer-0.02/
- * The algorithm is based on a spring-style layouter of a Java-based social
- * network tracker PieSpy written by Paul Mutton .
- *
- * This code is freely distributable under the MIT license. Commercial use is
- * hereby granted without any cost or restriction.
- *
- * Links:
- *
- * Graph Dracula JavaScript Framework:
- * http://graphdracula.net
- *
- /*--------------------------------------------------------------------------*/
-
-/*
- * Edge Factory
- */
-var AbstractEdge = function() {
-}
-AbstractEdge.prototype = {
- hide: function() {
- this.connection.fg.hide();
- this.connection.bg && this.bg.connection.hide();
- }
-};
-var EdgeFactory = function() {
- this.template = new AbstractEdge();
- this.template.style = new Object();
- this.template.style.directed = false;
- this.template.weight = 1;
-};
-EdgeFactory.prototype = {
- build: function(source, target) {
- var e = jQuery.extend(true, {}, this.template);
- e.source = source;
- e.target = target;
- return e;
- }
-};
-
-/*
- * Graph
- */
-var Graph = function() {
- this.nodes = {};
- this.edges = [];
- this.snapshots = []; // previous graph states TODO to be implemented
- this.edgeFactory = new EdgeFactory();
-};
-Graph.prototype = {
- /*
- * add a node
- * @id the node's ID (string or number)
- * @content (optional, dictionary) can contain any information that is
- * being interpreted by the layout algorithm or the graph
- * representation
- */
- addNode: function(id, content) {
- /* testing if node is already existing in the graph */
- if(this.nodes[id] == undefined) {
- this.nodes[id] = new Graph.Node(id, content);
- }
- return this.nodes[id];
- },
-
- addEdge: function(source, target, style) {
- var s = this.addNode(source);
- var t = this.addNode(target);
- var edge = this.edgeFactory.build(s, t);
- jQuery.extend(edge.style,style);
- s.edges.push(edge);
- this.edges.push(edge);
- // NOTE: Even directed edges are added to both nodes.
- t.edges.push(edge);
- },
-
- /* TODO to be implemented
- * Preserve a copy of the graph state (nodes, positions, ...)
- * @comment a comment describing the state
- */
- snapShot: function(comment) {
- /* FIXME
- var graph = new Graph();
- graph.nodes = jQuery.extend(true, {}, this.nodes);
- graph.edges = jQuery.extend(true, {}, this.edges);
- this.snapshots.push({comment: comment, graph: graph});
- */
- },
- removeNode: function(id) {
- delete this.nodes[id];
- for(var i = 0; i < this.edges.length; i++) {
- if (this.edges[i].source.id == id || this.edges[i].target.id == id) {
- this.edges.splice(i, 1);
- i--;
- }
- }
- }
-};
-
-/*
- * Node
- */
-Graph.Node = function(id, node){
- node = node || {};
- node.id = id;
- node.edges = [];
- node.hide = function() {
- this.hidden = true;
- this.shape && this.shape.hide(); /* FIXME this is representation specific code and should be elsewhere */
- for(i in this.edges)
- (this.edges[i].source.id == id || this.edges[i].target == id) && this.edges[i].hide && this.edges[i].hide();
- };
- node.show = function() {
- this.hidden = false;
- this.shape && this.shape.show();
- for(i in this.edges)
- (this.edges[i].source.id == id || this.edges[i].target == id) && this.edges[i].show && this.edges[i].show();
- };
- return node;
-};
-Graph.Node.prototype = {
-};
-
-/*
- * Renderer base class
- */
-Graph.Renderer = {};
-
-/*
- * Renderer implementation using RaphaelJS
- */
-Graph.Renderer.Raphael = function(element, graph, width, height) {
- this.width = width || 400;
- this.height = height || 400;
- var selfRef = this;
- this.r = Raphael(element, this.width, this.height);
- this.radius = 40; /* max dimension of a node */
- this.graph = graph;
- this.mouse_in = false;
-
- /* TODO default node rendering function */
- if(!this.graph.render) {
- this.graph.render = function() {
- return;
- }
- }
-
- /*
- * Dragging
- */
- this.isDrag = false;
- this.dragger = function (e) {
- this.dx = e.clientX;
- this.dy = e.clientY;
- selfRef.isDrag = this;
- this.set && this.set.animate({"fill-opacity": .1}, 200) && this.set.toFront();
- e.preventDefault && e.preventDefault();
- };
-
- var d = document.getElementById(element);
- d.onmousemove = function (e) {
- e = e || window.event;
- if (selfRef.isDrag) {
- var bBox = selfRef.isDrag.set.getBBox();
- // TODO round the coordinates here (eg. for proper image representation)
- var newX = e.clientX - selfRef.isDrag.dx + (bBox.x + bBox.width / 2);
- var newY = e.clientY - selfRef.isDrag.dy + (bBox.y + bBox.height / 2);
- /* prevent shapes from being dragged out of the canvas */
- var clientX = e.clientX - (newX < 20 ? newX - 20 : newX > selfRef.width - 20 ? newX - selfRef.width + 20 : 0);
- var clientY = e.clientY - (newY < 20 ? newY - 20 : newY > selfRef.height - 20 ? newY - selfRef.height + 20 : 0);
- selfRef.isDrag.set.translate(clientX - Math.round(selfRef.isDrag.dx), clientY - Math.round(selfRef.isDrag.dy));
- // console.log(clientX - Math.round(selfRef.isDrag.dx), clientY - Math.round(selfRef.isDrag.dy));
- for (var i in selfRef.graph.edges) {
- selfRef.graph.edges[i].connection && selfRef.graph.edges[i].connection.draw();
- }
- //selfRef.r.safari();
- selfRef.isDrag.dx = clientX;
- selfRef.isDrag.dy = clientY;
- }
- };
- d.onmouseup = function () {
- selfRef.isDrag && selfRef.isDrag.set.animate({"fill-opacity": .6}, 500);
- selfRef.isDrag = false;
- };
- this.draw();
-};
-Graph.Renderer.Raphael.prototype = {
- translate: function(point) {
- return [
- (point[0] - this.graph.layoutMinX) * this.factorX + this.radius,
- (point[1] - this.graph.layoutMinY) * this.factorY + this.radius
- ];
- },
-
- rotate: function(point, length, angle) {
- var dx = length * Math.cos(angle);
- var dy = length * Math.sin(angle);
- return [point[0]+dx, point[1]+dy];
- },
-
- draw: function() {
- this.factorX = (this.width - 2 * this.radius) / (this.graph.layoutMaxX - this.graph.layoutMinX);
- this.factorY = (this.height - 2 * this.radius) / (this.graph.layoutMaxY - this.graph.layoutMinY);
- for (i in this.graph.nodes) {
- this.drawNode(this.graph.nodes[i]);
- }
- for (var i = 0; i < this.graph.edges.length; i++) {
- this.drawEdge(this.graph.edges[i]);
- }
- },
-
- drawNode: function(node) {
- var point = this.translate([node.layoutPosX, node.layoutPosY]);
- node.point = point;
-
- /* if node has already been drawn, move the nodes */
- if(node.shape) {
- var oBBox = node.shape.getBBox();
- var opoint = { x: oBBox.x + oBBox.width / 2, y: oBBox.y + oBBox.height / 2};
- node.shape.translate(Math.round(point[0] - opoint.x), Math.round(point[1] - opoint.y));
- this.r.safari();
- return node;
- }/* else, draw new nodes */
-
- var shape;
-
- /* if a node renderer function is provided by the user, then use it
- or the default render function instead */
- if(!node.render) {
- node.render = function(r, node) {
- /* the default node drawing */
- var color = Raphael.getColor();
- var ellipse = r.ellipse(0, 0, 30, 20).attr({fill: color, stroke: color, "stroke-width": 2});
- /* set DOM node ID */
- ellipse.node.id = node.label || node.id;
- shape = r.set().
- push(ellipse).
- push(r.text(0, 30, node.label || node.id));
- return shape;
- }
- }
- /* or check for an ajax representation of the nodes */
- if(node.shapes) {
- // TODO ajax representation evaluation
- }
-
- shape = node.render(this.r, node).hide();
-
- shape.attr({"fill-opacity": .6});
- /* re-reference to the node an element belongs to, needed for dragging all elements of a node */
- shape.items.forEach(function(item){ item.set = shape; item.node.style.cursor = "move"; });
- shape.mousedown(this.dragger);
-
- var box = shape.getBBox();
- shape.translate(Math.round(point[0]-(box.x+box.width/2)),Math.round(point[1]-(box.y+box.height/2)))
- //console.log(box,point);
- node.hidden || shape.show();
- node.shape = shape;
- },
- drawEdge: function(edge) {
- /* if this edge already exists the other way around and is undirected */
- if(edge.backedge)
- return;
- if(edge.source.hidden || edge.target.hidden) {
- edge.connection && edge.connection.fg.hide() | edge.connection.bg && edge.connection.bg.hide();
- return;
- }
- /* if edge already has been drawn, only refresh the edge */
- if(!edge.connection) {
- edge.style && edge.style.callback && edge.style.callback(edge); // TODO move this somewhere else
- edge.connection = this.r.connection(edge.source.shape, edge.target.shape, edge.style);
- return;
- }
- //FIXME showing doesn't work well
- edge.connection.fg.show();
- edge.connection.bg && edge.connection.bg.show();
- edge.connection.draw();
- }
-};
-Graph.Layout = {};
-Graph.Layout.Spring = function(graph) {
- this.graph = graph;
- this.iterations = 500;
- this.maxRepulsiveForceDistance = 6;
- this.k = 2;
- this.c = 0.01;
- this.maxVertexMovement = 0.5;
- this.layout();
-};
-Graph.Layout.Spring.prototype = {
- layout: function() {
- this.layoutPrepare();
- for (var i = 0; i < this.iterations; i++) {
- this.layoutIteration();
- }
- this.layoutCalcBounds();
- },
-
- layoutPrepare: function() {
- for (i in this.graph.nodes) {
- var node = this.graph.nodes[i];
- node.layoutPosX = 0;
- node.layoutPosY = 0;
- node.layoutForceX = 0;
- node.layoutForceY = 0;
- }
-
- },
-
- layoutCalcBounds: function() {
- var minx = Infinity, maxx = -Infinity, miny = Infinity, maxy = -Infinity;
-
- for (i in this.graph.nodes) {
- var x = this.graph.nodes[i].layoutPosX;
- var y = this.graph.nodes[i].layoutPosY;
-
- if(x > maxx) maxx = x;
- if(x < minx) minx = x;
- if(y > maxy) maxy = y;
- if(y < miny) miny = y;
- }
-
- this.graph.layoutMinX = minx;
- this.graph.layoutMaxX = maxx;
- this.graph.layoutMinY = miny;
- this.graph.layoutMaxY = maxy;
- },
-
- layoutIteration: function() {
- // Forces on nodes due to node-node repulsions
-
- var prev = new Array();
- for(var c in this.graph.nodes) {
- var node1 = this.graph.nodes[c];
- for (var d in prev) {
- var node2 = this.graph.nodes[prev[d]];
- this.layoutRepulsive(node1, node2);
-
- }
- prev.push(c);
- }
-
- // Forces on nodes due to edge attractions
- for (var i = 0; i < this.graph.edges.length; i++) {
- var edge = this.graph.edges[i];
- this.layoutAttractive(edge);
- }
-
- // Move by the given force
- for (i in this.graph.nodes) {
- var node = this.graph.nodes[i];
- var xmove = this.c * node.layoutForceX;
- var ymove = this.c * node.layoutForceY;
-
- var max = this.maxVertexMovement;
- if(xmove > max) xmove = max;
- if(xmove < -max) xmove = -max;
- if(ymove > max) ymove = max;
- if(ymove < -max) ymove = -max;
-
- node.layoutPosX += xmove;
- node.layoutPosY += ymove;
- node.layoutForceX = 0;
- node.layoutForceY = 0;
- }
- },
-
- layoutRepulsive: function(node1, node2) {
- if (typeof node1 == 'undefined' || typeof node2 == 'undefined')
- return;
- var dx = node2.layoutPosX - node1.layoutPosX;
- var dy = node2.layoutPosY - node1.layoutPosY;
- var d2 = dx * dx + dy * dy;
- if(d2 < 0.01) {
- dx = 0.1 * Math.random() + 0.1;
- dy = 0.1 * Math.random() + 0.1;
- var d2 = dx * dx + dy * dy;
- }
- var d = Math.sqrt(d2);
- if(d < this.maxRepulsiveForceDistance) {
- var repulsiveForce = this.k * this.k / d;
- node2.layoutForceX += repulsiveForce * dx / d;
- node2.layoutForceY += repulsiveForce * dy / d;
- node1.layoutForceX -= repulsiveForce * dx / d;
- node1.layoutForceY -= repulsiveForce * dy / d;
- }
- },
-
- layoutAttractive: function(edge) {
- var node1 = edge.source;
- var node2 = edge.target;
-
- var dx = node2.layoutPosX - node1.layoutPosX;
- var dy = node2.layoutPosY - node1.layoutPosY;
- var d2 = dx * dx + dy * dy;
- if(d2 < 0.01) {
- dx = 0.1 * Math.random() + 0.1;
- dy = 0.1 * Math.random() + 0.1;
- var d2 = dx * dx + dy * dy;
- }
- var d = Math.sqrt(d2);
- if(d > this.maxRepulsiveForceDistance) {
- d = this.maxRepulsiveForceDistance;
- d2 = d * d;
- }
- var attractiveForce = (d2 - this.k * this.k) / this.k;
- if(edge.attraction == undefined) edge.attraction = 1;
- attractiveForce *= Math.log(edge.attraction) * 0.5 + 1;
-
- node2.layoutForceX -= attractiveForce * dx / d;
- node2.layoutForceY -= attractiveForce * dy / d;
- node1.layoutForceX += attractiveForce * dx / d;
- node1.layoutForceY += attractiveForce * dy / d;
- }
-};
-
-Graph.Layout.Ordered = function(graph, order) {
- this.graph = graph;
- this.order = order;
- this.layout();
-};
-Graph.Layout.Ordered.prototype = {
- layout: function() {
- this.layoutPrepare();
- this.layoutCalcBounds();
- },
-
- layoutPrepare: function(order) {
- for (i in this.graph.nodes) {
- var node = this.graph.nodes[i];
- node.layoutPosX = 0;
- node.layoutPosY = 0;
- }
- var counter = 0;
- for (i in this.order) {
- var node = this.order[i];
- node.layoutPosX = counter;
- node.layoutPosY = Math.random();
- counter++;
- }
- },
-
- layoutCalcBounds: function() {
- var minx = Infinity, maxx = -Infinity, miny = Infinity, maxy = -Infinity;
-
- for (i in this.graph.nodes) {
- var x = this.graph.nodes[i].layoutPosX;
- var y = this.graph.nodes[i].layoutPosY;
-
- if(x > maxx) maxx = x;
- if(x < minx) minx = x;
- if(y > maxy) maxy = y;
- if(y < miny) miny = y;
- }
-
- this.graph.layoutMinX = minx;
- this.graph.layoutMaxX = maxx;
-
- this.graph.layoutMinY = miny;
- this.graph.layoutMaxY = maxy;
- }
-};
-
-/*
- * usefull JavaScript extensions,
- */
-
-function log(a) {console.log&&console.log(a);}
-
-/*
- * Raphael Tooltip Plugin
- * - attaches an element as a tooltip to another element
- *
- * Usage example, adding a rectangle as a tooltip to a circle:
- *
- * paper.circle(100,100,10).tooltip(paper.rect(0,0,20,30));
- *
- * If you want to use more shapes, you'll have to put them into a set.
- *
- */
-Raphael.el.tooltip = function (tp) {
- this.tp = tp;
- this.tp.o = {x: 0, y: 0};
- this.tp.hide();
- this.hover(
- function(event){
- this.mousemove(function(event){
- this.tp.translate(event.clientX -
- this.tp.o.x,event.clientY - this.tp.o.y);
- this.tp.o = {x: event.clientX, y: event.clientY};
- });
- this.tp.show().toFront();
- },
- function(event){
- this.tp.hide();
- this.unmousemove();
- });
- return this;
-};
-
-/* For IE */
-if (!Array.prototype.forEach)
-{
- Array.prototype.forEach = function(fun /*, thisp*/)
- {
- var len = this.length;
- if (typeof fun != "function")
- throw new TypeError();
-
- var thisp = arguments[1];
- for (var i = 0; i < len; i++)
- {
- if (i in this)
- fun.call(thisp, this[i], i, this);
- }
- };
-}
diff --git a/luci-app-bmx6/files/www/luci-static/resources/bmx6/js/jquery-1.4.2.min.js b/luci-app-bmx6/files/www/luci-static/resources/bmx6/js/jquery-1.4.2.min.js
deleted file mode 100644
index 7c24308..0000000
--- a/luci-app-bmx6/files/www/luci-static/resources/bmx6/js/jquery-1.4.2.min.js
+++ /dev/null
@@ -1,154 +0,0 @@
-/*!
- * jQuery JavaScript Library v1.4.2
- * http://jquery.com/
- *
- * Copyright 2010, John Resig
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * Includes Sizzle.js
- * http://sizzlejs.com/
- * Copyright 2010, The Dojo Foundation
- * Released under the MIT, BSD, and GPL Licenses.
- *
- * Date: Sat Feb 13 22:33:48 2010 -0500
- */
-(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
-Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
-(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
-a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
-"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
-function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b