5G
This commit is contained in:
parent
e65679b443
commit
5500a26278
33
rooter/0basicapps/ext-command/Makefile
Normal file
33
rooter/0basicapps/ext-command/Makefile
Normal file
@ -0,0 +1,33 @@
|
||||
#Owned by DairyMan@Whirlpool
|
||||
#
|
||||
#Copyright GNU act.
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ext-command
|
||||
PKG_VERSION:=4.500
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ext-command
|
||||
SECTION:=utils
|
||||
CATEGORY:=ROOter
|
||||
SUBMENU:=Basic Applications
|
||||
TITLE:=support for Command
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/ext-command/description
|
||||
Helper scripts to enable command
|
||||
endef
|
||||
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/ext-command/install
|
||||
$(CP) ./files/* $(1)/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ext-command))
|
@ -0,0 +1,296 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2012 Jo-Philipp Wich <jow@openwrt.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
]]--
|
||||
|
||||
module("luci.controller.commands", package.seeall)
|
||||
|
||||
I18N = require "luci.i18n"
|
||||
translate = I18N.translate
|
||||
|
||||
function index()
|
||||
local multilock = luci.model.uci.cursor():get("custom", "multiuser", "multi") or "0"
|
||||
local rootlock = luci.model.uci.cursor():get("custom", "multiuser", "root") or "0"
|
||||
if (multilock == "0") or (multilock == "1" and rootlock == "1") then
|
||||
entry({"admin", "system", "commands"}, firstchild(), _(translate("Custom Commands")), 80)
|
||||
entry({"admin", "system", "commands", "dashboard"}, template("commands"), _(translate("Dashboard")), 1)
|
||||
entry({"admin", "system", "commands", "config"}, cbi("commands"), _(translate("Configure")), 2)
|
||||
entry({"admin", "system", "commands", "script"}, template("cmdedit"), _(translate("Scripts")), 3)
|
||||
entry({"admin", "system", "commands", "run"}, call("action_run"), nil, 3).leaf = true
|
||||
entry({"admin", "system", "commands", "download"}, call("action_download"), nil, 3).leaf = true
|
||||
end
|
||||
|
||||
entry({"admin", "system", "load_script"}, call("action_load_script"))
|
||||
entry({"admin", "system", "save_script"}, call("action_save_script"))
|
||||
entry({"admin", "system", "del_script"}, call("action_del_script"))
|
||||
|
||||
entry({"command"}, call("action_public"), nil, 1).leaf = true
|
||||
end
|
||||
|
||||
--- Decode a given string into arguments following shell quoting rules
|
||||
--- [[abc \def "foo\"bar" abc'def']] -> [[abc def]] [[foo"bar]] [[abcdef]]
|
||||
local function parse_args(str)
|
||||
local args = { }
|
||||
|
||||
local function isspace(c)
|
||||
if c == 9 or c == 10 or c == 11 or c == 12 or c == 13 or c == 32 then
|
||||
return c
|
||||
end
|
||||
end
|
||||
|
||||
local function isquote(c)
|
||||
if c == 34 or c == 39 or c == 96 then
|
||||
return c
|
||||
end
|
||||
end
|
||||
|
||||
local function isescape(c)
|
||||
if c == 92 then
|
||||
return c
|
||||
end
|
||||
end
|
||||
|
||||
local function ismeta(c)
|
||||
if c == 36 or c == 92 or c == 96 then
|
||||
return c
|
||||
end
|
||||
end
|
||||
|
||||
--- Convert given table of byte values into a Lua string and append it to
|
||||
--- the "args" table. Segment byte value sequence into chunks of 256 values
|
||||
--- to not trip over the parameter limit for string.char()
|
||||
local function putstr(bytes)
|
||||
local chunks = { }
|
||||
local csz = 256
|
||||
local upk = unpack
|
||||
local chr = string.char
|
||||
local min = math.min
|
||||
local len = #bytes
|
||||
local off
|
||||
|
||||
for off = 1, len, csz do
|
||||
chunks[#chunks+1] = chr(upk(bytes, off, min(off + csz - 1, len)))
|
||||
end
|
||||
|
||||
args[#args+1] = table.concat(chunks)
|
||||
end
|
||||
|
||||
--- Scan substring defined by the indexes [s, e] of the string "str",
|
||||
--- perform unquoting and de-escaping on the fly and store the result in
|
||||
--- a table of byte values which is passed to putstr()
|
||||
local function unquote(s, e)
|
||||
local off, esc, quote
|
||||
local res = { }
|
||||
|
||||
for off = s, e do
|
||||
local byte = str:byte(off)
|
||||
local q = isquote(byte)
|
||||
local e = isescape(byte)
|
||||
local m = ismeta(byte)
|
||||
|
||||
if e then
|
||||
esc = true
|
||||
elseif esc then
|
||||
if m then res[#res+1] = 92 end
|
||||
res[#res+1] = byte
|
||||
esc = false
|
||||
elseif q and quote and q == quote then
|
||||
quote = nil
|
||||
elseif q and not quote then
|
||||
quote = q
|
||||
else
|
||||
if m then res[#res+1] = 92 end
|
||||
res[#res+1] = byte
|
||||
end
|
||||
end
|
||||
|
||||
putstr(res)
|
||||
end
|
||||
|
||||
--- Find substring boundaries in "str". Ignore escaped or quoted
|
||||
--- whitespace, pass found start- and end-index for each substring
|
||||
--- to unquote()
|
||||
local off, esc, start, quote
|
||||
for off = 1, #str + 1 do
|
||||
local byte = str:byte(off)
|
||||
local q = isquote(byte)
|
||||
local s = isspace(byte) or (off > #str)
|
||||
local e = isescape(byte)
|
||||
|
||||
if esc then
|
||||
esc = false
|
||||
elseif e then
|
||||
esc = true
|
||||
elseif q and quote and q == quote then
|
||||
quote = nil
|
||||
elseif q and not quote then
|
||||
start = start or off
|
||||
quote = q
|
||||
elseif s and not quote then
|
||||
if start then
|
||||
unquote(start, off - 1)
|
||||
start = nil
|
||||
end
|
||||
else
|
||||
start = start or off
|
||||
end
|
||||
end
|
||||
|
||||
--- If the "quote" is still set we encountered an unfinished string
|
||||
if quote then
|
||||
unquote(start, #str)
|
||||
end
|
||||
|
||||
return args
|
||||
end
|
||||
|
||||
local function parse_cmdline(cmdid, args)
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
if uci:get("luci", cmdid) == "command" then
|
||||
local cmd = uci:get_all("luci", cmdid)
|
||||
local argv = parse_args(cmd.command)
|
||||
local i, v
|
||||
|
||||
if cmd.param == "1" and args then
|
||||
for i, v in ipairs(parse_args(luci.http.urldecode(args))) do
|
||||
argv[#argv+1] = v
|
||||
end
|
||||
end
|
||||
|
||||
for i, v in ipairs(argv) do
|
||||
if v:match("[^%w%.%-i/]") then
|
||||
argv[i] = '"%s"' % v:gsub('"', '\\"')
|
||||
end
|
||||
end
|
||||
|
||||
return argv
|
||||
end
|
||||
end
|
||||
|
||||
function action_run(...)
|
||||
local fs = require "nixio.fs"
|
||||
local argv = parse_cmdline(...)
|
||||
if argv then
|
||||
local outfile = os.tmpname()
|
||||
local errfile = os.tmpname()
|
||||
|
||||
local rv = os.execute(table.concat(argv, " ") .. " >%s 2>%s" %{ outfile, errfile })
|
||||
local stdout = fs.readfile(outfile, 1024 * 512) or ""
|
||||
local stderr = fs.readfile(errfile, 1024 * 512) or ""
|
||||
|
||||
fs.unlink(outfile)
|
||||
fs.unlink(errfile)
|
||||
|
||||
local binary = not not (stdout:match("[%z\1-\8\14-\31]"))
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
command = table.concat(argv, " "),
|
||||
stdout = not binary and stdout,
|
||||
stderr = stderr,
|
||||
exitcode = rv,
|
||||
binary = binary
|
||||
})
|
||||
else
|
||||
luci.http.status(404, translate("No such command"))
|
||||
end
|
||||
end
|
||||
|
||||
function action_download(...)
|
||||
local fs = require "nixio.fs"
|
||||
local argv = parse_cmdline(...)
|
||||
if argv then
|
||||
local fd = io.popen(table.concat(argv, " ") .. " 2>/dev/null")
|
||||
if fd then
|
||||
local chunk = fd:read(4096) or ""
|
||||
local name
|
||||
if chunk:match("[%z\1-\8\14-\31]") then
|
||||
luci.http.header("Content-Disposition", "attachment; filename=%s"
|
||||
% fs.basename(argv[1]):gsub("%W+", ".") .. ".bin")
|
||||
luci.http.prepare_content("application/octet-stream")
|
||||
else
|
||||
luci.http.header("Content-Disposition", "attachment; filename=%s"
|
||||
% fs.basename(argv[1]):gsub("%W+", ".") .. ".txt")
|
||||
luci.http.prepare_content("text/plain")
|
||||
end
|
||||
|
||||
while chunk do
|
||||
luci.http.write(chunk)
|
||||
chunk = fd:read(4096)
|
||||
end
|
||||
|
||||
fd:close()
|
||||
else
|
||||
luci.http.status(500, translate("Failed to execute command"))
|
||||
end
|
||||
else
|
||||
luci.http.status(404, "No such command")
|
||||
end
|
||||
end
|
||||
|
||||
function action_public(cmdid, args)
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
if cmdid and
|
||||
uci:get("luci", cmdid) == "command" and
|
||||
uci:get("luci", cmdid, "public") == "1"
|
||||
then
|
||||
action_download(cmdid, args)
|
||||
else
|
||||
luci.http.status(403, translate("Access to command denied"))
|
||||
end
|
||||
end
|
||||
|
||||
function action_load_script()
|
||||
local set = luci.http.formvalue("set")
|
||||
local rv ={}
|
||||
local file
|
||||
|
||||
file = io.open(set, "r")
|
||||
if file ~= nil then
|
||||
local tmp = file:read("*all")
|
||||
rv["text"] = tmp
|
||||
file:close()
|
||||
else
|
||||
rv["text"] = translate("No file found")
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
end
|
||||
|
||||
function action_save_script()
|
||||
local line = luci.http.formvalue("set")
|
||||
local rv ={}
|
||||
local file
|
||||
|
||||
s, e = line:find("|")
|
||||
name = line:sub(1,s-1)
|
||||
text = line:sub(e+1)
|
||||
|
||||
file = io.open(name, "w")
|
||||
file:write(text)
|
||||
file:close()
|
||||
os.execute("chmod 777 " .. name)
|
||||
|
||||
rv["name"] = name
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
end
|
||||
|
||||
function action_del_script()
|
||||
local name = luci.http.formvalue("set")
|
||||
local rv ={}
|
||||
os.remove(name)
|
||||
|
||||
rv["name"] = name
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
end
|
@ -0,0 +1,37 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2012 Jo-Philipp Wich <jow@openwrt.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
]]--
|
||||
|
||||
local m, s
|
||||
|
||||
m = Map("luci", translate("Custom Commands"),
|
||||
translate("This page allows you to configure custom shell commands which can be easily invoked from the web interface."))
|
||||
|
||||
s = m:section(TypedSection, "command", "")
|
||||
s.template = "cbi/tblsection"
|
||||
s.anonymous = true
|
||||
s.addremove = true
|
||||
|
||||
|
||||
s:option(Value, "name", translate("Description"),
|
||||
translate("A short textual description of the configured command"))
|
||||
|
||||
s:option(Value, "command", translate("Command"),
|
||||
translate("Command line to execute"))
|
||||
|
||||
s:option(Flag, "param", translate("Custom arguments"),
|
||||
translate("Allow the user to provide additional command line arguments"))
|
||||
|
||||
s:option(Flag, "public", translate("Public access"),
|
||||
translate("Allow executing the command and downloading its output without prior authentication"))
|
||||
|
||||
return m
|
@ -0,0 +1,186 @@
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/xhr.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
function savescript(btn)
|
||||
{
|
||||
var t = document.getElementById("script").value;
|
||||
if ( t.length == 0 )
|
||||
{
|
||||
alert("No script name!!");
|
||||
return false;
|
||||
}
|
||||
var tp = document.getElementById("path").value;
|
||||
if ( t.length == 0 )
|
||||
{
|
||||
alert("No script path!!");
|
||||
return false;
|
||||
}
|
||||
var txt = document.getElementById("txt").value;
|
||||
if ( txt.length == 0 )
|
||||
{
|
||||
alert("Script is blank!!");
|
||||
return false;
|
||||
}
|
||||
var length = tp.length;
|
||||
if ( tp.substr(length-1) != "/" )
|
||||
{
|
||||
tp = tp.concat("/");
|
||||
}
|
||||
var s = tp.concat(t);
|
||||
s = s.concat("|");
|
||||
s = s.concat(txt);
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "save_script")%>',
|
||||
{ set: s },
|
||||
function(x, rv)
|
||||
{
|
||||
name = rv.name;
|
||||
text = name.concat(" has been saved.")
|
||||
alert(text);
|
||||
}
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function delscript(btn)
|
||||
{
|
||||
var t = document.getElementById("script").value;
|
||||
if ( t.length == 0 )
|
||||
{
|
||||
alert("No script name!!");
|
||||
return false;
|
||||
}
|
||||
var tp = document.getElementById("path").value;
|
||||
if ( t.length == 0 )
|
||||
{
|
||||
alert("No script path!!");
|
||||
return false;
|
||||
}
|
||||
var length = tp.length;
|
||||
if ( tp.substr(length-1) != "/" )
|
||||
{
|
||||
tp = tp.concat("/");
|
||||
}
|
||||
var s = tp.concat(t);
|
||||
var del = "Delete ";
|
||||
del = del.concat(s);
|
||||
del = del.concat(" ?");
|
||||
var r=confirm(del);
|
||||
if (r==false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "del_script")%>',
|
||||
{ set: s },
|
||||
function(x, rv)
|
||||
{
|
||||
name = rv.name;
|
||||
text = name.concat(" has been deleted.")
|
||||
alert(text);
|
||||
document.getElementById("path").value="/usr/lib/scripts";
|
||||
document.getElementById("txt").value="";
|
||||
document.getElementById("script").value="";
|
||||
}
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function newscript(btn)
|
||||
{
|
||||
document.getElementById("path").value="/usr/lib/scripts";
|
||||
document.getElementById("txt").value="";
|
||||
document.getElementById("script").value="";
|
||||
return false;
|
||||
}
|
||||
|
||||
function loadscript(btn)
|
||||
{
|
||||
var t = document.getElementById("script").value;
|
||||
if ( t.length == 0 )
|
||||
{
|
||||
alert("No script name!!");
|
||||
return false;
|
||||
}
|
||||
var tp = document.getElementById("path").value;
|
||||
if ( t.length == 0 )
|
||||
{
|
||||
alert("No script path!!");
|
||||
return false;
|
||||
}
|
||||
document.getElementById("txt").value="";
|
||||
var length = tp.length;
|
||||
if ( tp.substr(length-1) != "/" )
|
||||
{
|
||||
tp = tp.concat("/");
|
||||
}
|
||||
var s = tp.concat(t);
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "load_script")%>',
|
||||
{ set: s },
|
||||
function(x, rv)
|
||||
{
|
||||
document.getElementById("txt").value=rv.text;
|
||||
}
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
function initial(btn)
|
||||
{
|
||||
document.getElementById("path").value="/usr/lib/scripts";
|
||||
document.getElementById("txt").value="";
|
||||
document.getElementById("script").value="";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
window.onload=initial;
|
||||
|
||||
//]]></script>
|
||||
|
||||
<form method="post" action="<%=REQUEST_URI%>">
|
||||
<div class="cbi-map" id="cbi-sms">
|
||||
<h2><a id="content" name="content"><%:Script Editing%></a></h2>
|
||||
<div class="cbi-map-descr"><%:Create, Edit and Save Scripts%></div>
|
||||
<fieldset class="cbi-section" id="cbi-read">
|
||||
<table id="sendmsg" width="600" border="0" style="display:table;">
|
||||
<tr>
|
||||
<td width="15%"><div align="left"><strong><%:Script Name :%></strong></div></td>
|
||||
<td width="70%"><input type="text" name="script" id="script" maxlength="50"></input></td>
|
||||
<td width="15%"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
<table id="sendmsg" width="600" border="0" style="display:table;">
|
||||
<tr>
|
||||
<td width="15%"><div align="left"><strong><%:Path to Script :%></strong></div></td>
|
||||
<td width="70%"><input type="text" name="path" id="path" maxlength="100"></input></td>
|
||||
<td width="15%"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table id="sendtxt" width="700" border="0" style="display:table;">
|
||||
<tr>
|
||||
<td width="100%">
|
||||
<textarea name="txt" id="txt" rows="6" style="width: 600px;" maxlength="10000"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table id="sendbtn" width="550" border="0" style="display:table;">
|
||||
<tr>
|
||||
<td width="5%"><input type="button" id="newbtn" class="cbi-button cbi-button-apply" value="<%:New%>" onclick="return newscript()" /></td>
|
||||
<td width="5%"><input type="button" id="loadbtn" class="cbi-button cbi-button-apply" value="<%:Load%>" onclick="return loadscript()" /></td>
|
||||
<td width="5%"><input type="button" id="savebtn" class="cbi-button cbi-button-apply" value="<%:Save%>" onclick="return savescript()" /></td>
|
||||
<td width="5%"><input type="button" id="delbtn" class="cbi-button cbi-button-apply" value="<%:Delete%>" onclick="return delscript()" /></td>
|
||||
<td width="80%"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
<%+footer%>
|
@ -0,0 +1,176 @@
|
||||
<%#
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2012 Jo-Philipp Wich <jow@openwrt.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
-%>
|
||||
|
||||
<% css = [[
|
||||
|
||||
.commandbox {
|
||||
height: 12em;
|
||||
width: 30%;
|
||||
float: left;
|
||||
height: 12em;
|
||||
margin: 5px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.commandbox h3 {
|
||||
font-size: 1.5em !important;
|
||||
line-height: 2em !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.commandbox input[type="text"] {
|
||||
width: 50% !important;
|
||||
}
|
||||
|
||||
.commandbox div {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 1.5em;
|
||||
}
|
||||
|
||||
]] -%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var stxhr = new XHR();
|
||||
|
||||
function command_run(id)
|
||||
{
|
||||
var args;
|
||||
var field = document.getElementById(id);
|
||||
if (field)
|
||||
args = encodeURIComponent(field.value);
|
||||
|
||||
var legend = document.getElementById('command-rc-legend');
|
||||
var output = document.getElementById('command-rc-output');
|
||||
|
||||
if (legend && output)
|
||||
{
|
||||
output.innerHTML =
|
||||
'<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> ' +
|
||||
'<%:Waiting for command to complete...%>'
|
||||
;
|
||||
|
||||
legend.parentNode.style.display = 'block';
|
||||
legend.style.display = 'inline';
|
||||
|
||||
stxhr.get('<%=luci.dispatcher.build_url("admin", "system", "commands", "run")%>/' + id + (args ? '/' + args : ''), null,
|
||||
function(x, st)
|
||||
{
|
||||
if (st)
|
||||
{
|
||||
if (st.binary)
|
||||
st.stdout = '[<%:Binary data not displayed, download instead.%>]';
|
||||
|
||||
legend.style.display = 'none';
|
||||
output.innerHTML = String.format(
|
||||
'<pre><strong># %h\n</strong>%h<span style="color:red">%h</span></pre>' +
|
||||
'<div class="alert-message warning">%s (<%:Code:%> %d)</div>',
|
||||
st.command, st.stdout, st.stderr,
|
||||
(st.exitcode == 0) ? '<%:Command successful%>' : '<%:Command failed%>',
|
||||
st.exitcode);
|
||||
}
|
||||
else
|
||||
{
|
||||
legend.style.display = 'none';
|
||||
output.innerHTML = '<span class="error"><%:Failed to execute command!%></span>';
|
||||
}
|
||||
|
||||
location.hash = '#output';
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function command_download(id)
|
||||
{
|
||||
var args;
|
||||
var field = document.getElementById(id);
|
||||
if (field)
|
||||
args = encodeURIComponent(field.value);
|
||||
|
||||
location.href = '<%=luci.dispatcher.build_url("admin", "system", "commands", "download")%>/' + id + (args ? '/' + args : '');
|
||||
}
|
||||
|
||||
function command_link(id)
|
||||
{
|
||||
var legend = document.getElementById('command-rc-legend');
|
||||
var output = document.getElementById('command-rc-output');
|
||||
|
||||
var args;
|
||||
var field = document.getElementById(id);
|
||||
if (field)
|
||||
args = encodeURIComponent(field.value);
|
||||
|
||||
if (legend && output)
|
||||
{
|
||||
var link = location.protocol + '//' + location.hostname +
|
||||
(location.port ? ':' + location.port : '') +
|
||||
location.pathname.split(';')[0] + 'command/' +
|
||||
id + (args ? '/' + args : '');
|
||||
|
||||
legend.style.display = 'none';
|
||||
output.parentNode.style.display = 'block';
|
||||
output.innerHTML = String.format(
|
||||
'<div class="alert-message"><%:Access command with%> <a href="%s">%s</a></div>',
|
||||
link, link
|
||||
);
|
||||
|
||||
location.hash = '#output';
|
||||
}
|
||||
}
|
||||
|
||||
//]]></script>
|
||||
|
||||
<%
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local commands = { }
|
||||
|
||||
uci:foreach("luci", "command", function(s) commands[#commands+1] = s end)
|
||||
%>
|
||||
|
||||
<form method="get" action="<%=pcdata(luci.http.getenv("REQUEST_URI"))%>">
|
||||
<div class="cbi-map">
|
||||
<h2><a id="content" name="content"><%:Custom Commands%></a></h2>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<% local _, command; for _, command in ipairs(commands) do %>
|
||||
<div class="commandbox">
|
||||
<h3><%=pcdata(command.name)%></h3>
|
||||
<p><%:Command:%> <code><%=pcdata(command.command)%></code></p>
|
||||
<% if command.param == "1" then %>
|
||||
<p><%:Arguments:%> <input type="text" id="<%=command['.name']%>" /></p>
|
||||
<% end %>
|
||||
<div>
|
||||
<input type="button" value="<%:Run%>" class="cbi-button cbi-button-apply" onclick="command_run('<%=command['.name']%>')" />
|
||||
<input type="button" value="<%:Download%>" class="cbi-button cbi-button-download" onclick="command_download('<%=command['.name']%>')" />
|
||||
<% if command.public == "1" then %>
|
||||
<input type="button" value="<%:Link%>" class="cbi-button cbi-button-link" onclick="command_link('<%=command['.name']%>')" />
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<br style="clear:both" /><br />
|
||||
<a name="output"></a>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<fieldset class="cbi-section" style="display:none">
|
||||
<legend id="command-rc-legend"><%:Collecting data...%></legend>
|
||||
<span id="command-rc-output"></span>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
<%+footer%>
|
@ -0,0 +1 @@
|
||||
0
|
35
rooter/0basicapps/ext-extra/Makefile
Normal file
35
rooter/0basicapps/ext-extra/Makefile
Normal file
@ -0,0 +1,35 @@
|
||||
#Owned by DairyMan@Whirlpool
|
||||
#
|
||||
#Copyright GNU act.
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ext-extra
|
||||
PKG_VERSION:=1.000
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ext-extra
|
||||
SECTION:=utils
|
||||
CATEGORY:=ROOter
|
||||
SUBMENU:=Basic Applications
|
||||
TITLE:=Add Scheduled Reboot
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/ext-extra/description
|
||||
Helper scripts to install Scheduled Reboot
|
||||
endef
|
||||
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/ext-extra/install
|
||||
$(CP) ./files/* $(1)/
|
||||
|
||||
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ext-extra))
|
7
rooter/0basicapps/ext-extra/files/etc/config/schedule
Normal file
7
rooter/0basicapps/ext-extra/files/etc/config/schedule
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
config reboot 'reboot'
|
||||
option enable '0'
|
||||
|
||||
config timezone 'timezone'
|
||||
option zonename 'UTC'
|
||||
|
@ -0,0 +1,13 @@
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.controller.schedule", package.seeall)
|
||||
|
||||
I18N = require "luci.i18n"
|
||||
translate = I18N.translate
|
||||
|
||||
function index()
|
||||
local page
|
||||
|
||||
page = entry({"admin", "services", "schedule"}, cbi("schedule"), _(translate("Scheduled Reboot")), 61)
|
||||
page.dependent = true
|
||||
end
|
@ -0,0 +1,29 @@
|
||||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2008-2013 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
local cronfile = "/etc/cronuser"
|
||||
|
||||
f = SimpleForm("crontab", translate("Scheduled Tasks"), translate("This is the system crontab in which scheduled tasks can be defined."))
|
||||
|
||||
t = f:field(TextValue, "crons")
|
||||
t.rmempty = true
|
||||
t.rows = 10
|
||||
function t.cfgvalue()
|
||||
return fs.readfile(cronfile) or ""
|
||||
end
|
||||
|
||||
function f.handle(self, state, data)
|
||||
if state == FORM_VALID then
|
||||
if data.crons then
|
||||
fs.writefile(cronfile, data.crons:gsub("\r\n", "\n"))
|
||||
else
|
||||
fs.writefile(cronfile, "")
|
||||
end
|
||||
luci.sys.call("/usr/lib/rooter/luci/croncat.sh")
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
return f
|
@ -0,0 +1,133 @@
|
||||
local utl = require "luci.util"
|
||||
|
||||
local sys = require "luci.sys"
|
||||
local zones = require "luci.sys.zoneinfo"
|
||||
local fs = require "nixio.fs"
|
||||
local conf = require "luci.config"
|
||||
|
||||
os.execute("/usr/lib/rooter/luci/reboot.sh 0")
|
||||
|
||||
m = Map("schedule", translate("Scheduled Reboot"), translate("Schedule a Router Reboot at a Specified Time"))
|
||||
|
||||
m.on_after_save = function(self)
|
||||
luci.sys.call("/usr/lib/rooter/luci/reboot.sh 1 &")
|
||||
end
|
||||
|
||||
d1 = m:section(TypedSection, "timezone", " ")
|
||||
|
||||
--o1 = d1:option(DummyValue, "_systime", translate("Local Time : "))
|
||||
--o1.template = "admin_system/clock_status"
|
||||
|
||||
o = d1:option(DummyValue, "zonename", translate("Timezone : "), translate("Be sure to set your Timezone correctly in System->System"))
|
||||
|
||||
d = m:section(TypedSection, "reboot", " ")
|
||||
|
||||
c1 = d:option(ListValue, "enable", " ");
|
||||
c1:value("0", translate("Disabled"))
|
||||
c1:value("1", translate("Enabled"))
|
||||
c1.default=0
|
||||
|
||||
sdhour = d:option(ListValue, "sdhour", translate("Reboot Time :"))
|
||||
sdhour.rmempty = true
|
||||
sdhour:value("0", "12:00 AM")
|
||||
sdhour:value("1", "12:15 AM")
|
||||
sdhour:value("2", "12:30 AM")
|
||||
sdhour:value("3", "12:45 AM")
|
||||
sdhour:value("4", "01:00 AM")
|
||||
sdhour:value("5", "01:15 AM")
|
||||
sdhour:value("6", "01:30 AM")
|
||||
sdhour:value("7", "01:45 AM")
|
||||
sdhour:value("8", "02:00 AM")
|
||||
sdhour:value("9", "02:15 AM")
|
||||
sdhour:value("10", "02:30 AM")
|
||||
sdhour:value("11", "02:45 AM")
|
||||
sdhour:value("12", "03:00 AM")
|
||||
sdhour:value("13", "03:15 AM")
|
||||
sdhour:value("14", "03:30 AM")
|
||||
sdhour:value("15", "03:45 AM")
|
||||
sdhour:value("16", "04:00 AM")
|
||||
sdhour:value("17", "04:15 AM")
|
||||
sdhour:value("18", "04:30 AM")
|
||||
sdhour:value("19", "04:45 AM")
|
||||
sdhour:value("20", "05:00 AM")
|
||||
sdhour:value("21", "05:15 AM")
|
||||
sdhour:value("22", "05:30 AM")
|
||||
sdhour:value("23", "05:45 AM")
|
||||
sdhour:value("24", "06:00 AM")
|
||||
sdhour:value("25", "06:15 AM")
|
||||
sdhour:value("26", "06:30 AM")
|
||||
sdhour:value("27", "06:45 AM")
|
||||
sdhour:value("28", "07:00 AM")
|
||||
sdhour:value("29", "07:15 AM")
|
||||
sdhour:value("30", "07:30 AM")
|
||||
sdhour:value("31", "07:45 AM")
|
||||
sdhour:value("32", "08:00 AM")
|
||||
sdhour:value("33", "08:15 AM")
|
||||
sdhour:value("34", "08:30 AM")
|
||||
sdhour:value("35", "08:45 AM")
|
||||
sdhour:value("36", "09:00 AM")
|
||||
sdhour:value("37", "09:15 AM")
|
||||
sdhour:value("38", "09:30 AM")
|
||||
sdhour:value("39", "09:45 AM")
|
||||
sdhour:value("40", "10:00 AM")
|
||||
sdhour:value("41", "10:15 AM")
|
||||
sdhour:value("42", "10:30 AM")
|
||||
sdhour:value("43", "10:45 AM")
|
||||
sdhour:value("44", "11:00 AM")
|
||||
sdhour:value("45", "11:15 AM")
|
||||
sdhour:value("46", "11:30 AM")
|
||||
sdhour:value("47", "11:45 AM")
|
||||
sdhour:value("48", "12:00 PM")
|
||||
sdhour:value("49", "12:15 PM")
|
||||
sdhour:value("50", "12:30 PM")
|
||||
sdhour:value("51", "12:45 PM")
|
||||
sdhour:value("52", "01:00 PM")
|
||||
sdhour:value("53", "01:15 PM")
|
||||
sdhour:value("54", "01:30 PM")
|
||||
sdhour:value("55", "01:45 PM")
|
||||
sdhour:value("56", "02:00 PM")
|
||||
sdhour:value("57", "02:15 PM")
|
||||
sdhour:value("58", "02:30 PM")
|
||||
sdhour:value("59", "02:45 PM")
|
||||
sdhour:value("60", "03:00 PM")
|
||||
sdhour:value("61", "03:15 PM")
|
||||
sdhour:value("62", "03:30 PM")
|
||||
sdhour:value("63", "03:45 PM")
|
||||
sdhour:value("64", "04:00 PM")
|
||||
sdhour:value("65", "04:15 PM")
|
||||
sdhour:value("66", "04:30 PM")
|
||||
sdhour:value("67", "04:45 PM")
|
||||
sdhour:value("68", "05:00 PM")
|
||||
sdhour:value("69", "05:15 PM")
|
||||
sdhour:value("70", "05:30 PM")
|
||||
sdhour:value("71", "05:45 PM")
|
||||
sdhour:value("72", "06:00 PM")
|
||||
sdhour:value("73", "06:15 PM")
|
||||
sdhour:value("74", "06:30 PM")
|
||||
sdhour:value("75", "06:45 PM")
|
||||
sdhour:value("76", "07:00 PM")
|
||||
sdhour:value("77", "07:15 PM")
|
||||
sdhour:value("78", "07:30 PM")
|
||||
sdhour:value("79", "07:45 PM")
|
||||
sdhour:value("80", "08:00 PM")
|
||||
sdhour:value("81", "08:15 PM")
|
||||
sdhour:value("82", "08:30 PM")
|
||||
sdhour:value("83", "08:45 PM")
|
||||
sdhour:value("84", "09:00 PM")
|
||||
sdhour:value("85", "09:15 PM")
|
||||
sdhour:value("86", "09:30 PM")
|
||||
sdhour:value("87", "09:45 PM")
|
||||
sdhour:value("88", "10:00 PM")
|
||||
sdhour:value("89", "10:15 PM")
|
||||
sdhour:value("90", "10:30 PM")
|
||||
sdhour:value("91", "10:45 PM")
|
||||
sdhour:value("92", "11:00 PM")
|
||||
sdhour:value("93", "11:15 PM")
|
||||
sdhour:value("94", "11:30 PM")
|
||||
sdhour:value("95", "11:45 PM")
|
||||
|
||||
sdhour:depends("enable", "1")
|
||||
sdhour.default = "0"
|
||||
|
||||
return m
|
||||
|
@ -0,0 +1,36 @@
|
||||
#!/bin/sh
|
||||
|
||||
log() {
|
||||
logger -t "Croncat" "$@"
|
||||
}
|
||||
|
||||
> /tmp/crontmp
|
||||
if [ -e /etc/crontabs/root ]; then
|
||||
while read -r line; do
|
||||
if [ -n "$line" ]; then
|
||||
if [ ${line: -1} == ";" ]; then
|
||||
echo "$line" >> /tmp/crontmp
|
||||
fi
|
||||
fi
|
||||
done < /etc/crontabs/root
|
||||
fi
|
||||
|
||||
if [ -f /etc/cronuser ]; then
|
||||
if [ -f /etc/cronbase ]; then
|
||||
cat /etc/cronbase /etc/cronuser > /etc/crontabs/root
|
||||
else
|
||||
cp /etc/cronuser /etc/crontabs/root
|
||||
fi
|
||||
else
|
||||
if [ -f /etc/cronbase ]; then
|
||||
cp /etc/cronbase /etc/crontabs/root
|
||||
else
|
||||
> /etc/crontabs/root
|
||||
fi
|
||||
fi
|
||||
cat /tmp/crontmp /etc/crontabs/root > /tmp/cronroot
|
||||
cp /tmp/cronroot /etc/crontabs/root
|
||||
rm /tmp/crontmp
|
||||
rm /tmp/cronroot
|
||||
|
||||
/etc/init.d/cron restart
|
@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
|
||||
log() {
|
||||
logger -t "Schedule Reboot" "$@"
|
||||
}
|
||||
|
||||
PARM=$1
|
||||
|
||||
if [ $PARM = "0" ]; then
|
||||
HO=$(uci get system.@system[-1].zonename)
|
||||
if [ -z $HO ]; then
|
||||
HO="UTC"
|
||||
fi
|
||||
uci set schedule.timezone.zonename="$HO"
|
||||
uci commit schedule
|
||||
fi
|
||||
|
||||
if [ $PARM = "1" ]; then
|
||||
sleep 5
|
||||
EN=$(uci get schedule.reboot.enable)
|
||||
if [ $EN = "1" ]; then
|
||||
SDHOUR=$(uci get schedule.reboot.sdhour)
|
||||
HOUR=`expr $SDHOUR / 4`
|
||||
let "TH = $HOUR * 4"
|
||||
let "TMP1 = $SDHOUR - $TH"
|
||||
let "MIN = $TMP1 * 15"
|
||||
echo "$MIN $HOUR * * * sleep 70 && touch /etc/banner && reboot -f" > /etc/cronbase
|
||||
else
|
||||
rm -f /etc/cronbase
|
||||
fi
|
||||
/usr/lib/rooter/luci/croncat.sh
|
||||
fi
|
36
rooter/0basicapps/ext-p910nd/Makefile
Normal file
36
rooter/0basicapps/ext-p910nd/Makefile
Normal file
@ -0,0 +1,36 @@
|
||||
#Owned by DairyMan@Whirlpool
|
||||
#
|
||||
#Copyright GNU act.
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ext-p910nd
|
||||
PKG_VERSION:=1.000
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ext-p910nd
|
||||
SECTION:=utils
|
||||
CATEGORY:=ROOter
|
||||
SUBMENU:=Basic Applications
|
||||
DEPENDS:=+p910nd +kmod-usb-printer +kmod-usb-ohci
|
||||
TITLE:=Install Print Server
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/ext-p910nd/description
|
||||
Helper scripts to install print Server
|
||||
endef
|
||||
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/ext-p910nd/install
|
||||
$(CP) ./files/* $(1)/
|
||||
|
||||
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ext-p910nd))
|
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@p910nd[-1]
|
||||
add ucitrack p910nd
|
||||
set ucitrack.@p910nd[-1].init=p910nd
|
||||
commit ucitrack
|
||||
EOF
|
||||
|
||||
rm -f /tmp/luci-indexcache
|
||||
exit 0
|
@ -0,0 +1,18 @@
|
||||
-- Copyright 2008 Yanira <forum-2008@email.de>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.controller.p910ndx", package.seeall)
|
||||
|
||||
I18N = require "luci.i18n"
|
||||
translate = I18N.translate
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/p910nd") then
|
||||
return
|
||||
end
|
||||
|
||||
local page
|
||||
|
||||
page = entry({"admin", "services", "p910ndx"}, cbi("p910ndx"), _(translate("Print Server")), 60)
|
||||
page.dependent = true
|
||||
end
|
@ -0,0 +1,59 @@
|
||||
--[[
|
||||
|
||||
LuCI p910nd
|
||||
(c) 2008 Yanira <forum-2008@email.de>
|
||||
(c) 2012 Jo-Philipp Wich <jow@openwrt.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
]]--
|
||||
|
||||
local uci = luci.model.uci.cursor_state()
|
||||
local net = require "luci.model.network"
|
||||
local m, s, p, b
|
||||
|
||||
m = Map("p910nd", translate("Print Server"),
|
||||
translatef("Support for USB Printers."))
|
||||
|
||||
net = net.init(m.uci)
|
||||
|
||||
s = m:section(TypedSection, "p910nd", translate("Settings"))
|
||||
s.addremove = true
|
||||
s.anonymous = true
|
||||
|
||||
s:option(Flag, "enabled", translate("enable"))
|
||||
|
||||
s:option(Value, "device", translate("Device")).rmempty = true
|
||||
|
||||
b = s:option(Value, "bind", translate("Interface"), translate("Specifies the interface to listen on."))
|
||||
b.template = "cbi/network_netlist"
|
||||
b.nocreate = true
|
||||
b.unspecified = true
|
||||
|
||||
function b.cfgvalue(...)
|
||||
local v = Value.cfgvalue(...)
|
||||
if v then
|
||||
return (net:get_status_by_address(v))
|
||||
end
|
||||
end
|
||||
|
||||
function b.write(self, section, value)
|
||||
local n = net:get_network(value)
|
||||
if n and n:ipaddr() then
|
||||
Value.write(self, section, n:ipaddr())
|
||||
end
|
||||
end
|
||||
|
||||
p = s:option(ListValue, "port", translate("Port"), translate("TCP listener port."))
|
||||
p.rmempty = true
|
||||
for i=0,9 do
|
||||
p:value(i, 9100+i)
|
||||
end
|
||||
|
||||
s:option(Flag, "bidirectional", translate("Bidirectional mode"))
|
||||
|
||||
return m
|
38
rooter/0basicapps/usb-storage/Makefile
Normal file
38
rooter/0basicapps/usb-storage/Makefile
Normal file
@ -0,0 +1,38 @@
|
||||
#Owned by DairyMan@Whirlpool
|
||||
#
|
||||
#Copyright GNU act.
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=usb-storage
|
||||
PKG_VERSION:=1.000
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/usb-storage
|
||||
SECTION:=utils
|
||||
CATEGORY:=ROOter
|
||||
SUBMENU:=Basic Applications
|
||||
DEPENDS:= +ntfs-3g +fdisk +kmod-usb-storage \
|
||||
+kmod-fs-ext4 +kmod-fs-vfat +kmod-nls-cp437 +kmod-nls-iso8859-1 +kmod-nls-utf8 \
|
||||
+block-mount +kmod-fs-exfat +kmod-fs-hfs +hd-idle
|
||||
TITLE:=Install USB Storage
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/usb-storage/description
|
||||
Helper scripts to install USB Storage
|
||||
endef
|
||||
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/usb-storage/install
|
||||
$(CP) ./files/* $(1)/
|
||||
|
||||
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,usb-storage))
|
2
rooter/0basicapps/usb-storage/files/etc/config/umount
Normal file
2
rooter/0basicapps/usb-storage/files/etc/config/umount
Normal file
@ -0,0 +1,2 @@
|
||||
config umount 'umount'
|
||||
option drive ''
|
@ -0,0 +1,68 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
. /lib/functions.sh
|
||||
|
||||
log() {
|
||||
logger -t "20-mount" "$@"
|
||||
}
|
||||
|
||||
blkdev=`dirname $DEVPATH`
|
||||
if [ `basename $blkdev` != "block" ]; then
|
||||
device=`basename $DEVPATH`
|
||||
if echo $device | grep -q "mtdblock"; then
|
||||
exit 0
|
||||
fi
|
||||
if [ -e /etc/sda_drop ]; then
|
||||
source /etc/sda_drop
|
||||
if echo $device | grep -q "$SDA"; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
if [ ! -e /usr/lib/sdcard/sdcard.sh ]; then
|
||||
/usr/lib/sdcard/sdcard.sh detect
|
||||
source /tmp/detect.file
|
||||
if [ $detect = "1" ]; then
|
||||
if echo $device | grep -q "mmcblk"; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if echo $device | grep -q "mmcblk"; then
|
||||
device1="SDCard"${device:8:2}
|
||||
else
|
||||
device1=$device
|
||||
fi
|
||||
|
||||
case "$ACTION" in
|
||||
add)
|
||||
mkdir -p /mnt/$device1
|
||||
# vfat & ntfs-3g check
|
||||
if [ `which fdisk` ]; then
|
||||
isntfs=`fdisk -l | grep $device | grep NTFS`
|
||||
isvfat=`fdisk -l | grep $device | grep FAT`
|
||||
isfuse=`lsmod | grep fuse`
|
||||
isntfs3g=`which ntfs-3g`
|
||||
else
|
||||
isntfs=""
|
||||
isvfat=""
|
||||
fi
|
||||
# mount with ntfs-3g if possible, else with default mount
|
||||
if [ "$isntfs" -a "$isfuse" -a "$isntfs3g" ]; then
|
||||
ntfs-3g -o nls=utf8 /dev/$device /mnt/$device1
|
||||
log "Mount /mnt/$device as NTFS"
|
||||
elif [ "$isvfat" ]; then
|
||||
mount -o rw,sync,umask=002,codepage=437,iocharset=iso8859-1 /dev/$device /mnt/$device1
|
||||
log "Mount /mnt/$device as FAT"
|
||||
else
|
||||
mount -o rw,sync /dev/$device /mnt/$device1
|
||||
log "Mount /mnt/$device as other"
|
||||
fi
|
||||
|
||||
chmod 777 /mnt/$device1
|
||||
chown nobody /mnt/$device1
|
||||
|
||||
if [ -e /usr/lib/sdcard/sdcard.sh ]; then
|
||||
/usr/lib/sdcard/sdcard.sh add
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
@ -0,0 +1,88 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
. /lib/functions.sh
|
||||
# Copyright (C) 2011 OpenWrt.org
|
||||
|
||||
log() {
|
||||
logger -t "30-mount" "$@"
|
||||
}
|
||||
|
||||
sanitize() {
|
||||
sed -e 's/[[:space:]]\+$//; s/[[:space:]]\+/_/g' "$@"
|
||||
}
|
||||
|
||||
blkdev=`dirname $DEVPATH`
|
||||
if [ `basename $blkdev` != "block" ]; then
|
||||
device=`basename $DEVPATH`
|
||||
if echo $device | grep -q "mtdblock"; then
|
||||
exit 0
|
||||
fi
|
||||
if [ ! -e /usr/lib/sdcard/sdcard.sh ]; then
|
||||
/usr/lib/sdcard/sdcard.sh detect
|
||||
source /tmp/detect.file
|
||||
if [ $detect = "1" ]; then
|
||||
if echo $device | grep -q "mmcblk"; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if echo $device | grep -q "mmcblk"; then
|
||||
device1="SDCard"${device:8:2}
|
||||
else
|
||||
device1=$device
|
||||
fi
|
||||
|
||||
if [ -e /etc/sda_drop ]; then
|
||||
source /etc/sda_drop
|
||||
if echo $device | grep -q "$SDA"; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$ACTION" in
|
||||
add)
|
||||
MT=$(cat /proc/mounts | grep "$device")
|
||||
if [ -z $MT ]; then
|
||||
exit 0
|
||||
fi
|
||||
DEVN=${DEVNAME:0:3}
|
||||
MODEL=$(sanitize "/sys/block/$DEVN/device/model")
|
||||
if [ -d /etc/ksmbd ]; then
|
||||
uci delete ksmbd.$device1
|
||||
uci set ksmbd.$device1=share
|
||||
uci set ksmbd.$device1.name=$device1
|
||||
uci set ksmbd.$device1.path=/mnt/$device1
|
||||
uci set ksmbd.$device1.read_only=no
|
||||
uci set ksmbd.$device1.guest_ok=yes
|
||||
uci set ksmbd.$device1.create_mask='0666'
|
||||
uci set ksmbd.$device1.dir_mask='0777'
|
||||
uci commit ksmbd
|
||||
/etc/init.d/ksmbd restart
|
||||
log "/mnt/$device1 shared as $device1"
|
||||
else
|
||||
if [ -d /etc/samba ]; then
|
||||
uci delete samba.$device1
|
||||
uci set samba.$device1=sambashare
|
||||
uci set samba.$device1.name=$device1
|
||||
uci set samba.$device1.path=/mnt/$device1
|
||||
uci set samba.$device1.read_only=no
|
||||
uci set samba.$device1.guest_ok=yes
|
||||
uci commit samba
|
||||
/etc/init.d/samba restart
|
||||
log "/mnt/$device1 shared as $device1"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
remove)
|
||||
log "remove /mnt/$device1"
|
||||
if [ -d /etc/ksmbd ]; then
|
||||
uci delete ksmbd.$device1
|
||||
uci commit ksmbd
|
||||
else
|
||||
if [ -d /etc/samba ]; then
|
||||
uci delete samba.$device1
|
||||
uci commit samba
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
@ -0,0 +1,41 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
. /lib/functions.sh
|
||||
|
||||
log() {
|
||||
logger -t "99-mount" "$@"
|
||||
}
|
||||
|
||||
|
||||
blkdev=`dirname $DEVPATH`
|
||||
if [ `basename $blkdev` != "block" ]; then
|
||||
device=`basename $DEVPATH`
|
||||
if echo $device | grep -q "mtdblock"; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ ! -e /usr/lib/sdcard/sdcard.sh ]; then
|
||||
/usr/lib/sdcard/sdcard.sh detect
|
||||
source /tmp/detect.file
|
||||
if [ $detect = "1" ]; then
|
||||
if echo $device | grep -q "mmcblk"; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if echo $device | grep -q "mmcblk"; then
|
||||
device1="SDCard"${device:8:2}
|
||||
else
|
||||
device1=$device
|
||||
fi
|
||||
|
||||
case "$ACTION" in
|
||||
remove)
|
||||
log "remove /mnt/$device1"
|
||||
umount -l /mnt/$device1
|
||||
rm -rf /mnt/$device1
|
||||
if [ -e /usr/lib/sdcard/sdcard.sh ]; then
|
||||
/usr/lib/sdcard/sdcard.sh remove
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@hd-idle[-1]
|
||||
add ucitrack hd-idle
|
||||
set ucitrack.@hd-idle[-1].init=hd-idle
|
||||
commit ucitrack
|
||||
EOF
|
||||
|
||||
rm -f /tmp/luci-indexcache
|
||||
exit 0
|
18
rooter/0basicapps/usb-storage/files/etc/umount
Normal file
18
rooter/0basicapps/usb-storage/files/etc/umount
Normal file
@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
log() {
|
||||
logger -t "Umount" "$@"
|
||||
}
|
||||
|
||||
sleep 5
|
||||
DRV=$(uci get umount.umount.drive)
|
||||
if [ -z $DRV ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
umount -l /mnt/$DRV
|
||||
|
||||
rm -rf /mnt/$DRV
|
||||
|
||||
uci set umount.umount.drive=''
|
||||
uci commit umount
|
@ -0,0 +1,17 @@
|
||||
-- Copyright 2008 Yanira <forum-2008@email.de>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.controller.hd_idle", package.seeall)
|
||||
|
||||
I18N = require "luci.i18n"
|
||||
translate = I18N.translate
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/hd-idle") then
|
||||
return
|
||||
end
|
||||
|
||||
local page
|
||||
page = entry({"admin", "services", "hd_idle"}, cbi("hd_idle"), _(translate("Hard Drive Idle")), 60)
|
||||
page.dependent = true
|
||||
end
|
@ -0,0 +1,11 @@
|
||||
module("luci.controller.umount", package.seeall)
|
||||
|
||||
I18N = require "luci.i18n"
|
||||
translate = I18N.translate
|
||||
|
||||
function index()
|
||||
local page
|
||||
|
||||
page = entry({"admin", "services", "umount"}, cbi("umount", {hidesavebtn=true, hideresetbtn=true}), translate("Safely Eject Drive"), 25)
|
||||
page.dependent = true
|
||||
end
|
@ -0,0 +1,28 @@
|
||||
-- Copyright 2008 Yanira <forum-2008@email.de>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
require("nixio.fs")
|
||||
|
||||
m = Map("hd-idle", "Hard Drive Idle",
|
||||
translate("This is a utility program for spinning-down external disks after a period of idle time."))
|
||||
|
||||
s = m:section(TypedSection, "hd-idle", translate("Settings"))
|
||||
s.anonymous = true
|
||||
|
||||
s:option(Flag, "enabled", translate("Enable"))
|
||||
|
||||
disk = s:option(Value, "disk", translate("Disk"))
|
||||
disk.rmempty = true
|
||||
for dev in nixio.fs.glob("/dev/[sh]d[a-z]") do
|
||||
disk:value(nixio.fs.basename(dev))
|
||||
end
|
||||
|
||||
s:option(Value, "idle_time_interval", translate("Idle-time")).default = 10
|
||||
s.rmempty = true
|
||||
unit = s:option(ListValue, "idle_time_unit", translate("Idle-time unit"))
|
||||
unit.default = "minutes"
|
||||
unit:value("minutes", translate("min"))
|
||||
unit:value("hours", translate("h"))
|
||||
unit.rmempty = true
|
||||
|
||||
return m
|
@ -0,0 +1,20 @@
|
||||
require("nixio.fs")
|
||||
|
||||
m = Map("umount", "Safely Eject a Drive",
|
||||
translate("Safely eject a drive from the router"))
|
||||
|
||||
m.on_after_save = function(self)
|
||||
luci.sys.call("/etc/umount &")
|
||||
end
|
||||
|
||||
drv = m:section(TypedSection, "umount", translate("Currently Mounted Drives"))
|
||||
drv.anonymous = true
|
||||
|
||||
disk = drv:option(Value, "drive", translate(" "), translate("Click Save and Apply to eject drive"))
|
||||
disk.rmempty = true
|
||||
for dev in nixio.fs.glob("/mnt/[sh]d[a-z][1-9]") do
|
||||
dv = nixio.fs.basename(dev)
|
||||
disk:value(nixio.fs.basename(dev))
|
||||
end
|
||||
|
||||
return m
|
88
rooter/0basicapps/usb-storage/files/usr/lib/sdcard/sdcard.sh
Normal file
88
rooter/0basicapps/usb-storage/files/usr/lib/sdcard/sdcard.sh
Normal file
@ -0,0 +1,88 @@
|
||||
#!/bin/sh
|
||||
|
||||
log() {
|
||||
logger -t "sdcard" "$@"
|
||||
}
|
||||
|
||||
h721() {
|
||||
if [ $1 = "add" ]; then
|
||||
echo "17" > /sys/class/gpio/export
|
||||
echo "out" > /sys/class/gpio/gpio17/direction
|
||||
echo 0 > /sys/class/gpio/gpio17/value
|
||||
else
|
||||
echo "17" > /sys/class/gpio/export
|
||||
echo "out" > /sys/class/gpio/gpio17/direction
|
||||
echo 1 > /sys/class/gpio/gpio17/value
|
||||
fi
|
||||
}
|
||||
|
||||
wg1608() {
|
||||
if [ $1 = "add" ]; then
|
||||
echo timer > /sys/class/leds/zbt-wg3526:green:signal/trigger
|
||||
echo 1000 > /sys/class/leds/zbt-wg3526:green:signal/delay_on
|
||||
echo 0 > /sys/class/leds/zbt-wg3526:green:signal/delay_off
|
||||
else
|
||||
echo timer > /sys/class/leds/zbt-wg3526:green:signal/trigger
|
||||
echo 0 > /sys/class/leds/zbt-wg3526:green:signal/delay_on
|
||||
echo 1000 > /sys/class/leds/zbt-wg3526:green:signal/delay_off
|
||||
fi
|
||||
}
|
||||
|
||||
ws7915() {
|
||||
if [ $1 = "add" ]; then
|
||||
echo timer > /sys/class/leds/sys/trigger
|
||||
echo 1000 > /sys/class/leds/sys/delay_on
|
||||
echo 0 > /sys/class/leds/sys/delay_off
|
||||
else
|
||||
echo timer > /sys/class/leds/sys/trigger
|
||||
echo 0 > /sys/class/leds/sys/delay_on
|
||||
echo 1000 > /sys/class/leds/sys/delay_off
|
||||
fi
|
||||
}
|
||||
|
||||
ws1688() {
|
||||
if [ $1 = "add" ]; then
|
||||
echo timer > /sys/class/leds/usb/trigger
|
||||
echo 1000 > /sys/class/leds/usb/delay_on
|
||||
echo 0 > /sys/class/leds/usb/delay_off
|
||||
else
|
||||
echo timer > /sys/class/leds/usb/trigger
|
||||
echo 0 > /sys/class/leds/usb/delay_on
|
||||
echo 1000 > /sys/class/leds/usb/delay_off
|
||||
fi
|
||||
}
|
||||
|
||||
ACTION=$1
|
||||
model=$(cat /tmp/sysinfo/model)
|
||||
|
||||
case $ACTION in
|
||||
"add"|"remove" )
|
||||
mod=$(echo $model | grep "H721")
|
||||
if [ $mod ]; then
|
||||
h721 $ACTION
|
||||
fi
|
||||
mod=$(echo $model | grep "WG1608")
|
||||
if [ $mod ]; then
|
||||
wg1608 $ACTION
|
||||
fi
|
||||
mod=$(echo $model | grep "WS7915")
|
||||
if [ $mod ]; then
|
||||
ws7915 $ACTION
|
||||
fi
|
||||
|
||||
mod=$(echo $model | grep "WS1688")
|
||||
if [ $mod ]; then
|
||||
ws1688 $ACTION
|
||||
fi
|
||||
;;
|
||||
"detect" )
|
||||
mod=$(echo $model | grep "Raspberry")
|
||||
if [ $mod ]; then
|
||||
echo 'detect="'"1"'"' > /tmp/detect.file
|
||||
else
|
||||
echo 'detect="'"0"'"' > /tmp/detect.file
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
|
35
rooter/0basicsupport/ext-buttons/Makefile
Normal file
35
rooter/0basicsupport/ext-buttons/Makefile
Normal file
@ -0,0 +1,35 @@
|
||||
#Owned by DairyMan@Whirlpool
|
||||
#
|
||||
#Copyright GNU act.
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ext-buttons
|
||||
PKG_VERSION:=1.000
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ext-buttons
|
||||
SECTION:=utils
|
||||
CATEGORY:=ROOter
|
||||
SUBMENU:=Basic Support
|
||||
TITLE:=Install button support
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/ext-buttons/description
|
||||
Helper scripts to install button support
|
||||
endef
|
||||
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/ext-buttons/install
|
||||
$(CP) ./files/* $(1)/
|
||||
|
||||
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ext-buttons))
|
56
rooter/0basicsupport/ext-buttons/files/etc/btnaction.sh
Normal file
56
rooter/0basicsupport/ext-buttons/files/etc/btnaction.sh
Normal file
@ -0,0 +1,56 @@
|
||||
#!/bin/sh
|
||||
|
||||
FUNC=$1
|
||||
|
||||
reset_short() {
|
||||
passwd -d root
|
||||
reboot -f
|
||||
}
|
||||
|
||||
reset_long() {
|
||||
mtd -r erase rootfs_data
|
||||
}
|
||||
|
||||
wifi() {
|
||||
STATEFILE="/tmp/wifionoff.state"
|
||||
|
||||
if [ $# -eq 1 ]; then
|
||||
case $1 in
|
||||
"up"|"on")
|
||||
STATE=off
|
||||
;;
|
||||
"down"|"off")
|
||||
STATE=on
|
||||
;;
|
||||
esac
|
||||
else
|
||||
if [ ! -e ${STATEFILE} ]; then
|
||||
STATE=on
|
||||
else
|
||||
. ${STATEFILE}
|
||||
fi
|
||||
fi
|
||||
if [ -z ${STATE} ]; then
|
||||
STATE=on
|
||||
fi
|
||||
|
||||
if [ ${STATE} == "on" ]; then
|
||||
/sbin/wifi down
|
||||
STATE=off
|
||||
else
|
||||
/sbin/wifi up
|
||||
STATE=on
|
||||
fi
|
||||
|
||||
echo "STATE=${STATE}" > ${STATEFILE}
|
||||
}
|
||||
|
||||
if [ $FUNC = "reset_short" ]; then
|
||||
reset_short
|
||||
fi
|
||||
if [ $FUNC = "reset_long" ]; then
|
||||
reset_long
|
||||
fi
|
||||
if [ $FUNC = "wifi" ]; then
|
||||
wifi $2
|
||||
fi
|
@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
do_button () {
|
||||
local button
|
||||
local action
|
||||
local handler
|
||||
local min
|
||||
local max
|
||||
|
||||
config_get button $1 button
|
||||
config_get action $1 action
|
||||
config_get handler $1 handler
|
||||
config_get min $1 min
|
||||
config_get max $1 max
|
||||
|
||||
[ "$ACTION" = "$action" -a "$BUTTON" = "$button" -a -n "$handler" ] && {
|
||||
[ -z "$min" -o -z "$max" ] && eval $handler
|
||||
[ -n "$min" -a -n "$max" ] && {
|
||||
[ $min -le $SEEN -a $max -ge $SEEN ] && eval $handler
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config_load system
|
||||
config_foreach do_button button
|
@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
log() {
|
||||
logger -t "Button Checker " "$@"
|
||||
}
|
||||
|
||||
log "Button Name : $BUTTON Action : $ACTION"
|
||||
|
||||
log "$ACTION $SEEN"
|
||||
|
16
rooter/0basicsupport/ext-buttons/files/etc/init.d/buttons
Normal file
16
rooter/0basicsupport/ext-buttons/files/etc/init.d/buttons
Normal file
@ -0,0 +1,16 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2006 OpenWrt.org
|
||||
|
||||
log() {
|
||||
logger -t "Buttons" "$@"
|
||||
}
|
||||
|
||||
START=98
|
||||
|
||||
start() {
|
||||
local BTN=$(uci -q get system.@button[-1].button)
|
||||
}
|
||||
|
||||
stop() {
|
||||
log "Stopping Buttons"
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
module("luci.controller.buttons", package.seeall)
|
||||
|
||||
I18N = require "luci.i18n"
|
||||
translate = I18N.translate
|
||||
|
||||
function index()
|
||||
local page
|
||||
local multilock = luci.model.uci.cursor():get("custom", "multiuser", "multi") or "0"
|
||||
local rootlock = luci.model.uci.cursor():get("custom", "multiuser", "root") or "0"
|
||||
if (multilock == "0") or (multilock == "1" and rootlock == "1") then
|
||||
page = entry({"admin", "system", "buttons"}, cbi("buttons/buttons"), _(translate("Buttons")), 65)
|
||||
page.dependent = true
|
||||
end
|
||||
end
|
@ -0,0 +1,44 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
m = Map("system", translate("Buttons"),
|
||||
translate("This page allows the configuration of custom button actions"))
|
||||
|
||||
s = m:section(TypedSection, "button", "")
|
||||
s.anonymous = true
|
||||
s.addremove = true
|
||||
|
||||
s:option(Value, "button", translate("Name"))
|
||||
|
||||
act = s:option(ListValue, "action",
|
||||
translate("Action"),
|
||||
translate("Specifies the button state to handle"))
|
||||
|
||||
act:value("released")
|
||||
act:value("pressed")
|
||||
act.default = "released"
|
||||
|
||||
s:option(Value, "handler",
|
||||
translate("Handler"),
|
||||
translate("Path to executable which handles the button event"))
|
||||
|
||||
min = s:option(Value, "min", translate("Minimum hold time"))
|
||||
min.rmempty = true
|
||||
min:depends("action", "released")
|
||||
|
||||
max = s:option(Value, "max", translate("Maximum hold time"))
|
||||
max.rmempty = true
|
||||
max:depends("action", "released")
|
||||
|
||||
return m
|
35
rooter/0basicsupport/ext-sms/Makefile
Normal file
35
rooter/0basicsupport/ext-sms/Makefile
Normal file
@ -0,0 +1,35 @@
|
||||
#Owned by DairyMan@Whirlpool
|
||||
#
|
||||
#Copyright GNU act.
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ext-sms
|
||||
PKG_VERSION:=1.000
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ext-sms
|
||||
SECTION:=utils
|
||||
CATEGORY:=ROOter
|
||||
SUBMENU:=Basic Support
|
||||
TITLE:=Install SMS support
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/ext-sms/description
|
||||
Helper scripts to install SMS on ROOter
|
||||
endef
|
||||
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/ext-sms/install
|
||||
$(CP) ./files/* $(1)/
|
||||
|
||||
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ext-sms))
|
@ -0,0 +1,160 @@
|
||||
module("luci.controller.sms", package.seeall)
|
||||
|
||||
I18N = require "luci.i18n"
|
||||
translate = I18N.translate
|
||||
|
||||
function index()
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
|
||||
|
||||
if not fs.stat("/etc/nosms") then
|
||||
local page
|
||||
page = entry({"admin", "modem", "sms"}, template("rooter/sms"), translate("短信功能"), 35)
|
||||
page.dependent = true
|
||||
|
||||
end
|
||||
|
||||
entry({"admin", "modem", "check_read"}, call("action_check_read"))
|
||||
entry({"admin", "modem", "del_sms"}, call("action_del_sms"))
|
||||
entry({"admin", "modem", "send_sms"}, call("action_send_sms"))
|
||||
entry({"admin", "modem", "change_sms"}, call("action_change_sms"))
|
||||
entry({"admin", "modem", "change_smsdn"}, call("action_change_smsdn"))
|
||||
entry({"admin", "modem", "change_smsflag"}, call("action_change_smsflag"))
|
||||
end
|
||||
|
||||
function trim(s)
|
||||
return (s:gsub("^%s*(.-)%s*$", "%1"))
|
||||
end
|
||||
|
||||
function action_send_sms()
|
||||
if package.path:find(";/usr/lib/sms/?.lua") == nil then
|
||||
package.path = package.path .. ";/usr/lib/sms/?.lua"
|
||||
end
|
||||
smsnum = luci.model.uci.cursor():get("modem", "general", "smsnum")
|
||||
local set = luci.http.formvalue("set")
|
||||
local number = trim(string.sub(set, 1, 20))
|
||||
local txt = string.sub(set, 21)
|
||||
local utf8togsm = require "utf8togsm"
|
||||
utf8togsm.chktxt(txt)
|
||||
local msg = utf8togsm["msg"]
|
||||
local dcs = utf8togsm["dcs"]
|
||||
txt = utf8togsm["txt"]
|
||||
local rv = {}
|
||||
local file = nil
|
||||
local k = 1
|
||||
local status
|
||||
local rfname = "/tmp/smssendstatus0000"
|
||||
if msg == nil then
|
||||
os.execute("if [ -e " .. rfname .. " ]; then rm " ..rfname .. "; fi")
|
||||
os.execute("lua /usr/lib/sms/sendsms.lua " .. smsnum .. " " .. number .. " " .. dcs .. " " .. txt .. " 0000")
|
||||
os.execute("sleep 3")
|
||||
repeat
|
||||
file = io.open(rfname, "r")
|
||||
if file == nil then
|
||||
os.execute("sleep 1")
|
||||
end
|
||||
k = k + 1
|
||||
until k > 25 or file ~=nil
|
||||
if file == nil then
|
||||
status = translate('Sending attempt timed out (fail)')
|
||||
else
|
||||
status = file:read("*line")
|
||||
file:close()
|
||||
os.remove (rfname)
|
||||
end
|
||||
else
|
||||
status = msg
|
||||
end
|
||||
rv["status"] = status
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
end
|
||||
|
||||
function action_del_sms()
|
||||
local set = tonumber(luci.http.formvalue("set"))
|
||||
if set ~= nil and set > 0 then
|
||||
set = set - 1;
|
||||
smsnum = luci.model.uci.cursor():get("modem", "general", "smsnum")
|
||||
os.execute("/usr/lib/sms/delsms.sh " .. smsnum .. " " .. set)
|
||||
os.execute("touch /tmp/smswakeup" .. smsnum)
|
||||
end
|
||||
end
|
||||
|
||||
function action_check_read()
|
||||
local rv ={}
|
||||
local file
|
||||
local line
|
||||
smsnum = luci.model.uci.cursor():get("modem", "general", "smsnum")
|
||||
conn = "Modem #" .. smsnum
|
||||
rv["conntype"] = conn
|
||||
support = luci.model.uci.cursor():get("modem", "modem" .. smsnum, "sms")
|
||||
rv["ready"] = "0"
|
||||
rv["menable"] = "0"
|
||||
rv["mslots"] = "0"
|
||||
if support == "1" then
|
||||
rv["ready"] = "1"
|
||||
result = "/tmp/smsresult" .. smsnum .. ".at"
|
||||
file = io.open(result, "r")
|
||||
if file ~= nil then
|
||||
file:close()
|
||||
file = io.open("/tmp/smstext" .. smsnum, "r")
|
||||
if file == nil then
|
||||
rv["ready"] = "3"
|
||||
else
|
||||
rv["menable"] = luci.model.uci.cursor():get("modem", "sms", "menable")
|
||||
rv["mslots"] = luci.model.uci.cursor():get("modem", "sms", "slots")
|
||||
rv["ready"] = "2"
|
||||
local tmp = file:read("*line")
|
||||
rv["used"] = tmp
|
||||
tmp = file:read("*line")
|
||||
rv["max"] = tmp
|
||||
full = nil
|
||||
|
||||
repeat
|
||||
for j = 1, 4 do
|
||||
line = file:read("*line")
|
||||
if line ~= nil then
|
||||
if j == 3 then
|
||||
full = full .. string.char(29)
|
||||
local i = tonumber(line)
|
||||
for k = 1, i do
|
||||
line = file:read("*line")
|
||||
full = full .. line
|
||||
if k < i then
|
||||
full = full .. '<br />'
|
||||
end
|
||||
end
|
||||
else
|
||||
if full == nil then
|
||||
full = line
|
||||
else
|
||||
full = full .. string.char(29) .. line
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
until line == nil
|
||||
file:close()
|
||||
rv["line"] = full
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
end
|
||||
|
||||
function action_change_sms()
|
||||
os.execute("/usr/lib/rooter/luci/modemchge.sh sms 1")
|
||||
end
|
||||
|
||||
function action_change_smsdn()
|
||||
os.execute("/usr/lib/rooter/luci/modemchge.sh sms 0")
|
||||
end
|
||||
|
||||
function action_change_smsflag()
|
||||
local set = tonumber(luci.http.formvalue("set"))
|
||||
os.execute("/usr/lib/sms/toggle.sh " .. set)
|
||||
end
|
||||
|
@ -0,0 +1,525 @@
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/xhr.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
reading = 0;
|
||||
init = 0;
|
||||
indx = -1;
|
||||
index = [];
|
||||
recread = [];
|
||||
number = [];
|
||||
tdate = [];
|
||||
ttime = [];
|
||||
ttext =[];
|
||||
selectline = -1;
|
||||
|
||||
XHR.poll(20, '<%=luci.dispatcher.build_url("admin", "modem", "check_read")%>', null,
|
||||
function(x, rv)
|
||||
{
|
||||
var ss = rv.ready;
|
||||
document.getElementById('conntype').innerHTML=rv.conntype;
|
||||
if ( ss == "0" )
|
||||
{
|
||||
clearListBox("smsList");
|
||||
document.getElementById('message').innerHTML="";
|
||||
document.getElementById('total').innerHTML="";
|
||||
document.getElementById('used').innerHTML="";
|
||||
document.getElementById('mslots').innerHTML="";
|
||||
document.getElementById('menb').checked=false;
|
||||
document.getElementById('supported').innerHTML="<%:模块未适配短信支持/未连接到模块%>";
|
||||
}
|
||||
if ( ss == "1" )
|
||||
{
|
||||
clearListBox("smsList");
|
||||
document.getElementById('message').innerHTML="";
|
||||
document.getElementById('total').innerHTML="";
|
||||
document.getElementById('used').innerHTML="";
|
||||
document.getElementById('mslots').innerHTML="";
|
||||
document.getElementById('menb').checked=false;
|
||||
document.getElementById('supported').innerHTML="<%:您有未读的短信,请前往查看%>";
|
||||
}
|
||||
if ( ss == "3" )
|
||||
{
|
||||
document.getElementById('supported').innerHTML="<%:消息读取有问题%>";
|
||||
}
|
||||
if ( ss == "2" )
|
||||
{
|
||||
document.getElementById('supported').innerHTML="<%:存在的短信%>";
|
||||
clearListBox("smsList");
|
||||
document.getElementById('total').innerHTML=rv.max;
|
||||
document.getElementById('used').innerHTML=rv.used;
|
||||
if ( parseInt(rv.used) == parseInt(rv.max) )
|
||||
{
|
||||
alternateColor('red','total');
|
||||
alternateColor('red','used');
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById('total').style.color = "default";
|
||||
document.getElementById('used').style.color = "default";
|
||||
}
|
||||
document.getElementById('mslots').innerHTML=rv.mslots;
|
||||
if ( init == 0 )
|
||||
{
|
||||
var me = rv.menable;
|
||||
if ( me == "0" )
|
||||
{
|
||||
document.getElementById('menb').checked=false;
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById('menb').checked=true;
|
||||
}
|
||||
init = 1;
|
||||
}
|
||||
if (rv.used == "0")
|
||||
{
|
||||
document.getElementById('supported').innerHTML="<%:SIM卡上没有短信%>";
|
||||
}
|
||||
else
|
||||
{
|
||||
var line=rv.line;
|
||||
var arr=(line.split("\x1D"));
|
||||
var len = arr.length;
|
||||
indx = 0;
|
||||
var i;
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
index[indx] = parseInt(arr[i]);
|
||||
number[indx] = arr[i+1];
|
||||
ttext[indx] = arr[i+2];
|
||||
var txtline = arr[i+3];
|
||||
txtline = txtline.replace(/ /g,"\240");
|
||||
|
||||
var select = document.getElementById("smsList");
|
||||
select.options[select.options.length] = new Option(txtline, indx);
|
||||
i = i + 3;
|
||||
indx = indx + 1;
|
||||
}
|
||||
if ( indx != -1 )
|
||||
{
|
||||
if ( selectline == -1 )
|
||||
{
|
||||
select.value = 0;
|
||||
document.getElementById('message').innerHTML=ttext[0];
|
||||
selectline = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( selectline > indx-1 )
|
||||
{
|
||||
selectline = indx -1 ;
|
||||
}
|
||||
select.value = selectline;
|
||||
document.getElementById('message').innerHTML=ttext[selectline];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
document.getElementById('message').innerHTML=" ";
|
||||
document.getElementById('total').innerHTML="0";
|
||||
document.getElementById('used').innerHTML="0";
|
||||
document.getElementById('mslots').innerHTML="0";
|
||||
|
||||
function alternateColor(color, textId, myInterval)
|
||||
{
|
||||
if(!myInterval)
|
||||
{
|
||||
myInterval = 500;
|
||||
}
|
||||
var colors = ['grey', color];
|
||||
var currentColor = 1;
|
||||
document.getElementById(textId).style.color = colors[0];
|
||||
setInterval(function()
|
||||
{
|
||||
if ( document.getElementById(textId).style.color == 'default' )
|
||||
{
|
||||
return;
|
||||
}
|
||||
document.getElementById(textId).style.color = colors[currentColor];
|
||||
if (currentColor < colors.length-1) {
|
||||
++currentColor;
|
||||
} else {
|
||||
currentColor = 0;
|
||||
}
|
||||
}, myInterval);
|
||||
}
|
||||
|
||||
function clearListBox(listboxID)
|
||||
{
|
||||
var mylistbox = document.getElementById(listboxID);
|
||||
if(mylistbox == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
while(mylistbox.length > 0)
|
||||
{
|
||||
mylistbox.remove(0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
function changetxt()
|
||||
{
|
||||
var s = document.getElementById("smsList").value;
|
||||
selectline = s;
|
||||
document.getElementById('message').innerHTML=ttext[s];
|
||||
}
|
||||
|
||||
function sendsms()
|
||||
{
|
||||
if ( reading > 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var s = document.getElementById("sendto").value;
|
||||
//document.getElementById('rding').innerHTML=s.length;
|
||||
if ( s.length == 0 )
|
||||
{
|
||||
alert("<%:请输入电话号码!!%>");
|
||||
return false;
|
||||
}
|
||||
s = s.trim();
|
||||
if ( isNaN(s) == true )
|
||||
{
|
||||
alert("<%:错误的电话号码!!%>");
|
||||
return false;
|
||||
}
|
||||
var num = s.concat(" ");
|
||||
num = num.substr(0, 20);
|
||||
var t = document.getElementById("txtmessage").value;
|
||||
if ( t.length == 0 )
|
||||
{
|
||||
alert("<%:Message is blank!!%>");
|
||||
return false;
|
||||
}
|
||||
if ( t.length > 160 )
|
||||
{
|
||||
t = t.substr(0, 160);
|
||||
}
|
||||
num = num.concat(t);
|
||||
alert("<%:SMS will be queued for processing.\nA status update will follow.%>");
|
||||
document.getElementById("sstat").innerHTML="<%:状态 :消息正在发送%>";
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "send_sms")%>',
|
||||
{ set: num },
|
||||
function(x, rv)
|
||||
{
|
||||
var status = rv.status;
|
||||
alert(status);
|
||||
document.getElementById("sstat").innerHTML="";
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function delsms()
|
||||
{
|
||||
if ( selectline == -1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var r=confirm("<%:确认删除选中消息 ?%>");
|
||||
if (r==false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var s = document.getElementById("smsList").value;
|
||||
var dx = index[s];
|
||||
dx = dx + 1;
|
||||
clearListBox("smsList");
|
||||
document.getElementById('message').style.color = "red";
|
||||
document.getElementById('message').innerHTML="<%:短信将被删除,同步到列表可能会很久(反复提交删除申请一样很久)%>";
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "del_sms")%>',
|
||||
{ set: dx },
|
||||
function()
|
||||
{
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "check_read")%>', null,
|
||||
function(x, rv)
|
||||
{
|
||||
var ss = rv.ready;
|
||||
document.getElementById('message').style.color = "initial";
|
||||
document.getElementById('conntype').innerHTML=rv.conntype;
|
||||
if ( ss == "1" )
|
||||
{
|
||||
clearListBox("smsList");
|
||||
document.getElementById('message').innerHTML="";
|
||||
document.getElementById('total').innerHTML="";
|
||||
document.getElementById('used').innerHTML="";
|
||||
document.getElementById('supported').innerHTML="<%:您有未读的短信,请前往查看%>";
|
||||
}
|
||||
if ( ss == "3" )
|
||||
{
|
||||
document.getElementById('supported').innerHTML="<%:消息读取有问题%>";
|
||||
}
|
||||
if ( ss == "2" )
|
||||
{
|
||||
document.getElementById('supported').innerHTML="<%:存在短信%>";
|
||||
clearListBox("smsList");
|
||||
document.getElementById('total').innerHTML=rv.max;
|
||||
document.getElementById('used').innerHTML=rv.used;
|
||||
var line=rv.line;
|
||||
var arr=(line.split("\x1D"));
|
||||
var len = arr.length;
|
||||
indx = 0;
|
||||
var i;
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
index[indx] = parseInt(arr[i]);
|
||||
number[indx] = arr[i+1];
|
||||
ttext[indx] = arr[i+2];
|
||||
var txtline = arr[i+3];
|
||||
txtline = txtline.replace(/ /g,"\240");
|
||||
|
||||
var select = document.getElementById("smsList");
|
||||
select.options[select.options.length] = new Option(txtline, indx);
|
||||
i = i + 3;
|
||||
indx = indx + 1;
|
||||
}
|
||||
if ( indx != -1 )
|
||||
{
|
||||
if ( selectline == -1 )
|
||||
{
|
||||
select.value = 0;
|
||||
document.getElementById('message').innerHTML=ttext[0];
|
||||
selectline = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( selectline > indx-1 )
|
||||
{
|
||||
selectline = indx -1 ;
|
||||
}
|
||||
select.value = selectline;
|
||||
document.getElementById('message').innerHTML=ttext[selectline];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function replysms()
|
||||
{
|
||||
if ( reading > 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var s = document.getElementById("smsList").value;
|
||||
if ( selectline == -1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById('sendmsg').style.display="table";
|
||||
document.getElementById('sendtxt').style.display="table";
|
||||
document.getElementById('sendbtn').style.display="table";
|
||||
document.getElementById('sendtitle').style.display="block";
|
||||
document.getElementById("sendto").value=number[s];
|
||||
document.getElementById("txtmessage").value="";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function newsms()
|
||||
{
|
||||
if ( reading > 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
document.getElementById('sendmsg').style.display="table";
|
||||
document.getElementById('sendtxt').style.display="table";
|
||||
document.getElementById('sendbtn').style.display="table";
|
||||
document.getElementById('sendtitle').style.display="block";
|
||||
document.getElementById("sendto").value="";
|
||||
document.getElementById("txtmessage").value="";
|
||||
return false;
|
||||
}
|
||||
|
||||
function modemtoggle(btn)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Changing...%>';
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "change_sms")%>',
|
||||
null,
|
||||
function(x, rv)
|
||||
{
|
||||
btn.disabled = false;
|
||||
btn.value = '<%:下一个模块%>';
|
||||
}
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function modemtoggledn(btn)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Changing...%>';
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "change_smsdn")%>',
|
||||
null,
|
||||
function(x, rv)
|
||||
{
|
||||
btn.disabled = false;
|
||||
btn.value = '<%:Prev Modem%>';
|
||||
}
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function memenable(btn)
|
||||
{
|
||||
dx = 0;
|
||||
if ( btn.checked == true )
|
||||
{
|
||||
dx = 1;
|
||||
}
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "change_smsflag")%>',
|
||||
{ set: dx },
|
||||
function()
|
||||
{
|
||||
}
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
//]]></script>
|
||||
|
||||
<form method="post" action="<%=REQUEST_URI%>">
|
||||
<div class="cbi-map" id="cbi-sms">
|
||||
<h2><a id="content" name="content"><%:短信收发页面%></a></h2>
|
||||
<div class="cbi-map-descr"><%:通过模块发送和接收文本消息%></div>
|
||||
<fieldset class="cbi-section" id="cbi-read">
|
||||
<legend><%:通信模块信息%></legend>
|
||||
<table width="550" border="0">
|
||||
<tr>
|
||||
<td width="40%"><ul id="supported"></ul></td>
|
||||
<td width="17%"><strong id="conntype"></strong></td>
|
||||
<td width="12%">
|
||||
<input type="button" class="cbi-button cbi-button-apply" value="<%:上一个模块%>" onclick="return modemtoggledn(this)" />
|
||||
</td>
|
||||
<td width="31%">
|
||||
<input type="button" class="cbi-button cbi-button-apply" value="<%:下一个模块%>" onclick="return modemtoggle(this)" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<legend><%:收到的短信%></legend>
|
||||
|
||||
<table width="550" border="0">
|
||||
<tr>
|
||||
<td width="18%"><div align="center"><strong><%:SIM可存放的短信空间 (条)%></strong></div></td>
|
||||
<td width="18%"><div align="center"><strong><%:已使用的SIM短信空间 (条)%></strong></div></td>
|
||||
<td width="34%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><div align="center"><ul id="total"></ul></div></td>
|
||||
<td><div align="center"><ul id="used"></ul></div></td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table width="550" border="0">
|
||||
<tr>
|
||||
<td width="3%"> </td>
|
||||
<td width="20%"><div align="left"><%:启用模块到SIM卡的短信传输%></div></td>
|
||||
<td width="8%">
|
||||
<input type="checkbox" id="menb" onclick="memenable(this)" />
|
||||
</td>
|
||||
<td width="16%"><div align="left"><strong><u><%:模块上的未读信息数量%></u></strong></div></td>
|
||||
<td width="34%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td><div align="center"><ul id="mslots"></ul></div></td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table width="700" border="0">
|
||||
<tr>
|
||||
<td width="4%"><div align="center"><strong><u><%:已读状态%></u></strong></div></td>
|
||||
<td width="18%"><div align="left"><strong><u><%:发件人%></u></strong></div></td>
|
||||
<td width="8%"><div align="left"><strong><u><%:Date%></u></strong></div></td>
|
||||
<td width="11%"><div align="left"><strong><u><%:时间%></u></strong></div></td>
|
||||
<td width="35%"><div align="left"><strong><u><%:短信%></u></strong></div></td>
|
||||
|
||||
<td width="24%"><div align="left"> </div></td>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table width="700" border="0">
|
||||
<tr>
|
||||
<td width="100%">
|
||||
<select name="smslist" id="smsList" size="5" style="width: 700px; font-size:15px; font-family:monospace; line-height:27px; float:left; height:130px;" onchange="changetxt()">
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table width="550" border="0">
|
||||
<tr>
|
||||
<td width="15%"><div align="left"><strong><%:短信内容 :%></strong></div></td>
|
||||
<td width="70%"><ul id="message"></ul></td>
|
||||
<td width="15%"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table width="550" border="0">
|
||||
<tr>
|
||||
<td width="17%"><input type="button" id="delbtn" class="cbi-button cbi-button-apply" value="<%:删除短信%>" onclick="return delsms()" /></td>
|
||||
<td width="17%"><input type="button" id="replybtn" class="cbi-button cbi-button-apply" value="<%:回复短信%>" onclick="return replysms()" /></td>
|
||||
<td width="17%"><input type="button" id="newbtn" class="cbi-button cbi-button-apply" value="<%:新建短信%>" onclick="return newsms()" /></td>
|
||||
<td width="49%"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<legend id="sendtitle" style="display:block;"><%:短信会话%></legend>
|
||||
|
||||
<table id="sendmsg" width="600" border="0" style="display:table;">
|
||||
<tr>
|
||||
<td width="15%"><div align="left"><strong><%:收件人 :%></strong></div></td>
|
||||
<td width="70%"><input name="sendto" id="sendto" maxlength="20"></input></td>
|
||||
<td width="15%"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table id="sendtxt" width="700" border="0" style="display:table;">
|
||||
<tr>
|
||||
|
||||
<td width="100%">
|
||||
<textarea name="txtmessage" id="txtmessage" rows="6" style="width: 600px;" maxlength="160"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table id="sendbtn" width="550" border="0" style="display:table;">
|
||||
<tr>
|
||||
<td width="17%"><input type="button" id="sendbtn" class="cbi-button cbi-button-apply" value="<%:Send%>" onclick="return sendsms()" /></td>
|
||||
<td width="13%"> </td>
|
||||
<td width="70%"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table width="550" border="0">
|
||||
<tr>
|
||||
<td width="15%"><div align="left"><strong><%:短信发送状态 :%></strong></div></td>
|
||||
<td width="70%"><ul style="color:red" id="sstat"></ul></td>
|
||||
<td width="15%"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
<%+footer%>
|
||||
|
41
rooter/0basicsupport/ext-sms/files/usr/lib/sms/delsms.sh
Normal file
41
rooter/0basicsupport/ext-sms/files/usr/lib/sms/delsms.sh
Normal file
@ -0,0 +1,41 @@
|
||||
#!/bin/sh
|
||||
|
||||
ROOTER=/usr/lib/rooter
|
||||
|
||||
log() {
|
||||
logger -t "Delete SMS" "$@"
|
||||
}
|
||||
|
||||
CURRMODEM=$1
|
||||
shift 1
|
||||
SLOTS="$@"
|
||||
|
||||
COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport)
|
||||
|
||||
SMSLOC=$(uci -q get modem.modem$CURRMODEM.smsloc)
|
||||
|
||||
LOCKDIR="/tmp/smslock$CURRMODEM"
|
||||
PIDFILE="${LOCKDIR}/PID"
|
||||
|
||||
while [ 1 -lt 6 ]; do
|
||||
if mkdir "${LOCKDIR}" &>/dev/null; then
|
||||
echo "$$" > "${PIDFILE}"
|
||||
for SLOT in $SLOTS
|
||||
do
|
||||
ATCMDD="AT+CPMS=\"$SMSLOC\";+CMGD=$SLOT"
|
||||
OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
done
|
||||
uci set modem.modem$CURRMODEM.smsnum=999
|
||||
uci commit modem
|
||||
break
|
||||
else
|
||||
OTHERPID="$(cat "${PIDFILE}")"
|
||||
if [ $? = 0 ]; then
|
||||
if ! kill -0 $OTHERPID &>/dev/null; then
|
||||
rm -rf "${LOCKDIR}"
|
||||
fi
|
||||
fi
|
||||
sleep 1
|
||||
fi
|
||||
done
|
||||
rm -rf "${LOCKDIR}"
|
79
rooter/0basicsupport/ext-sms/files/usr/lib/sms/pack7bit.lua
Normal file
79
rooter/0basicsupport/ext-sms/files/usr/lib/sms/pack7bit.lua
Normal file
@ -0,0 +1,79 @@
|
||||
local pack7bit = {}
|
||||
|
||||
function hasbit(x, p)
|
||||
return x % (p + p) >= p
|
||||
end
|
||||
|
||||
function bitand(x, y)
|
||||
local p = 1; local z = 0; local limit = x > y and x or y
|
||||
while p <= limit do
|
||||
if hasbit(x, p) and hasbit(y, p) then
|
||||
z = z + p
|
||||
end
|
||||
p = p + p
|
||||
end
|
||||
return z
|
||||
end
|
||||
|
||||
function bitor(x, y)
|
||||
local p = 1; local z = 0; local limit = x > y and x or y
|
||||
while p <= limit do
|
||||
if hasbit(x, p) or hasbit(y, p) then
|
||||
z = z + p
|
||||
end
|
||||
p = p + p
|
||||
end
|
||||
return z
|
||||
end
|
||||
|
||||
function bitright(x, y)
|
||||
return math.floor(x / 2 ^ y)
|
||||
end
|
||||
|
||||
function bitleft(x, y)
|
||||
return x * 2 ^ y
|
||||
end
|
||||
|
||||
function pack7bit.pack(udl, txt)
|
||||
maxb = math.ceil((tonumber(udl, 16) / 8) * 7)
|
||||
udtab = {}
|
||||
ii = 1
|
||||
jj = 1
|
||||
kk = 0
|
||||
repeat
|
||||
ch = tonumber(txt:sub(jj, jj + 1), 16)
|
||||
if ii == 1 then
|
||||
udtab[kk + 1] = ch
|
||||
elseif ii == 2 then
|
||||
udtab[kk] = bitor(bitleft(bitand(ch, 1), 7), udtab[kk])
|
||||
udtab[kk + 1] = bitright(bitand(ch, 126), 1)
|
||||
elseif ii == 3 then
|
||||
udtab[kk] = bitor(bitleft(bitand(ch, 3), 6), udtab[kk])
|
||||
udtab[kk + 1] = bitright(bitand(ch, 124), 2)
|
||||
elseif ii == 4 then
|
||||
udtab[kk] = bitor(bitleft(bitand(ch, 7), 5), udtab[kk])
|
||||
udtab[kk + 1] = bitright(bitand(ch, 120), 3)
|
||||
elseif ii == 5 then
|
||||
udtab[kk] = bitor(bitleft((bitand(ch, 15)), 4), udtab[kk])
|
||||
udtab[kk + 1] = bitright(bitand(ch, 112), 4)
|
||||
elseif ii == 6 then
|
||||
udtab[kk] = bitor(bitleft(bitand(ch, 31), 3), udtab[kk])
|
||||
udtab[kk + 1] = bitright(bitand(ch, 96), 5)
|
||||
elseif ii == 7 then
|
||||
udtab[kk] = bitor(bitleft(bitand(ch, 63), 2), udtab[kk])
|
||||
udtab[kk + 1] = bitright(bitand(ch, 64), 6)
|
||||
else
|
||||
udtab[kk] = bitor(bitleft(ch, 1), udtab[kk])
|
||||
ii = 0
|
||||
kk = kk - 1
|
||||
end
|
||||
ii = ii + 1
|
||||
jj = jj + 2
|
||||
kk = kk + 1
|
||||
until jj > #txt
|
||||
for jj = 1, maxb do
|
||||
udtab[jj] = string.format("%02X", udtab[jj])
|
||||
end
|
||||
pack7bit["pdu"] = table.concat(udtab)
|
||||
end
|
||||
return pack7bit
|
168
rooter/0basicsupport/ext-sms/files/usr/lib/sms/processsms
Normal file
168
rooter/0basicsupport/ext-sms/files/usr/lib/sms/processsms
Normal file
@ -0,0 +1,168 @@
|
||||
#!/bin/sh
|
||||
|
||||
ROOTER=/usr/lib/rooter
|
||||
|
||||
log() {
|
||||
logger -t "sms process" "$@"
|
||||
}
|
||||
|
||||
CURRMODEM=$1
|
||||
|
||||
log "SMS Supported Modem$CURRMODEM"
|
||||
|
||||
COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport)
|
||||
|
||||
LOCKDIR="/tmp/smslock$CURRMODEM"
|
||||
PIDFILE="${LOCKDIR}/PID"
|
||||
rm -rf "${LOCKDIR}"
|
||||
|
||||
idV=$(uci -q get modem.modem$CURRMODEM.idV)
|
||||
idP=$(uci -q get modem.modem$CURRMODEM.idP)
|
||||
MODEMID="$idV${idP:0:3}"
|
||||
|
||||
ATCMDD="AT+CMGF=0"
|
||||
OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
sleep 1
|
||||
ATCMDD="AT+CPMS=\"SM\",\"SM\",\"SM\""
|
||||
OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
MAXED=$(echo "$OX" | cut -d, -f2 | grep -o "[0-9]\{1,3\}")
|
||||
if [ "$MAXED" == "0" -a "$MODEMID" != "119968a" ]; then
|
||||
ATCMDD="AT+CPMS=\"ME\",\"ME\",\"ME\""
|
||||
OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
uci set modem.modem$CURRMODEM.smsloc="ME"
|
||||
SMSLOC="ME"
|
||||
MEM3="ME"
|
||||
else
|
||||
uci set modem.modem$CURRMODEM.smsloc="SM"
|
||||
SMSLOC="SM"
|
||||
MEM3="SM"
|
||||
fi
|
||||
sleep 1
|
||||
uci set modem.modem$CURRMODEM.smsnum=999
|
||||
uci commit modem
|
||||
ATCMDD="AT+CPMS=\"ME\""
|
||||
OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
MESC=$(echo "$OX" | grep -o "+CPMS:.*" | awk -F, '{print $1}' | grep -o "[0-9]\{1,3\}")
|
||||
METC=$(echo "$OX" | grep -o "+CPMS:.*" | awk -F, '{print $2}' | grep -o "[0-9]\{1,3\}")
|
||||
MESLOT="0"
|
||||
MESCc=""
|
||||
if [ "x$MESC" = "x" ]; then
|
||||
MESC="0"
|
||||
fi
|
||||
if [ "x$METC" = "x" ]; then
|
||||
METC="0"
|
||||
MESC="0"
|
||||
SMSLOC="SM"
|
||||
fi
|
||||
uci set modem.sms.slots=$MESC
|
||||
uci commit modem
|
||||
sleep 1
|
||||
|
||||
rm -f /tmp/smsresult$CURRMODEM".at"
|
||||
> /tmp/smsslots$CURRMODEM
|
||||
HH=$(date +%H)
|
||||
|
||||
while true; do
|
||||
SLEEP="20"
|
||||
while true; do
|
||||
if mkdir "${LOCKDIR}" &>/dev/null; then
|
||||
echo "$$" > "${PIDFILE}"
|
||||
if [ "$METC" != "0" ]; then
|
||||
ATCMDD="AT+CPMS=\"ME\",\"$SMSLOC\",\"$MEM3\""
|
||||
SX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
USED=$(echo "$SX" | cut -d, -f1 | grep -o "[0-9]\{1,3\}")
|
||||
MESCc="$USED"
|
||||
MAXED=$(echo "$SX" | cut -d, -f2 | grep -o "[0-9]\{1,3\}")
|
||||
fi
|
||||
if [ $SMSLOC == "SM" ]; then
|
||||
ATCMDD="AT+CPMS=\"SM\",\"$SMSLOC\",\"$MEM3\""
|
||||
SX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
USED=$(echo "$SX" | cut -d, -f1 | grep -o "[0-9]\{1,3\}")
|
||||
MAXED=$(echo "$SX" | cut -d, -f2 | grep -o "[0-9]\{1,3\}")
|
||||
if [ -n "$MESCc" -a "$MESCc" != "$MESC" ]; then
|
||||
MESC=$MESCc
|
||||
uci set modem.sms.slots=$MESC
|
||||
uci commit modem
|
||||
fi
|
||||
if [ $USED == $MAXED -a $MEM3 == "SM" ]; then
|
||||
ATCMDD="AT+CPMS=\"SM\",\"SM\",\"ME\""
|
||||
OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
MEM3="ME"
|
||||
else
|
||||
if [ $USED != $MAXED -a $MEM3 == "ME" ]; then
|
||||
ATCMDD="AT+CPMS=\"SM\",\"SM\",\"SM\""
|
||||
OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
MEM3="SM"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [ $MAXED -eq 0 ]; then
|
||||
SLEEP="900"
|
||||
fi
|
||||
if [ $USED -eq $(uci get modem.modem$CURRMODEM.smsnum) ] && [ $HH -eq $(date +%H) ]; then
|
||||
if [ $MEM3 == "SM" -a $USED -lt $MAXED -a $MESC -gt 0 -a $(uci -q get modem.sms.menable) == 1 ]; then
|
||||
ATCMDD="AT+CPMS=\"ME\";+CMGR=$MESLOT;+CPMS=\"SM\""
|
||||
OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
Rstat=$(echo "$OX" | grep -o "+CMGR:[^,]\+" | grep -o "[0-3]")
|
||||
PDU=$(echo "$OX" | grep -o "[0-9A-F]\{30,\}")
|
||||
PDUL=$(echo "$OX" | grep -o "+CMGR:.*" | grep -o ",[0-9]\{1,\}" | grep -o "[0-9]\{1,3\}")
|
||||
if [ -n "$PDU" -a -n "$PDUL" -a -n "$Rstat" ]; then
|
||||
if [ ${#PDUL} -eq 2 ]; then
|
||||
PDUL="0$PDUL"
|
||||
fi
|
||||
ATCMDD="$PDUL,SM,$Rstat,$PDU"
|
||||
OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "smswrite.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
MREF=$(echo "$OX" | grep -o "[0-9]\{1,3\}")
|
||||
if [ ${#MREF} -gt 0 ]; then
|
||||
echo "$MREF" >> /tmp/smsslots$CURRMODEM
|
||||
ATCMDD="AT+CPMS=\"ME\";+CMGD=$MESLOT;+CPMS=\"SM\""
|
||||
OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
fi
|
||||
MESC=$(($MESC - 1))
|
||||
uci set modem.sms.slots=$MESC
|
||||
uci commit modem
|
||||
SLEEP="5"
|
||||
fi
|
||||
MESLOT=$(($MESLOT + 1))
|
||||
if [ $MESLOT -gt $METC -o $MESC == "0" ]; then
|
||||
MESLOT="0"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
log "Reread SMS Messages on Modem $CURRMODEM"
|
||||
echo "$SX" > /tmp/smstemp$CURRMODEM
|
||||
ATCMDD="AT+CMGL=4"
|
||||
SX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
SX=$(echo "$SX" | sed -e "s/+CMGL:/+CMGL: /g")
|
||||
echo "$SX" >> /tmp/smstemp$CURRMODEM
|
||||
uci set modem.modem$CURRMODEM.smsnum=$USED
|
||||
uci commit modem
|
||||
mv /tmp/smstemp$CURRMODEM /tmp/smsresult$CURRMODEM.at
|
||||
lua /usr/lib/sms/smsread.lua $CURRMODEM
|
||||
HH=$(date +%H)
|
||||
SLEEP="5"
|
||||
fi
|
||||
break
|
||||
else
|
||||
OTHERPID="$(cat "${PIDFILE}")"
|
||||
if [ $? = 0 ]; then
|
||||
if ! kill -0 $OTHERPID &>/dev/null; then
|
||||
rm -rf "${LOCKDIR}"
|
||||
fi
|
||||
fi
|
||||
sleep 1
|
||||
fi
|
||||
done
|
||||
rm -rf "${LOCKDIR}"
|
||||
n=1
|
||||
until [ $n -ge $SLEEP ]
|
||||
do
|
||||
sleep 1
|
||||
if [ -e /tmp/smswakeup$CURRMODEM ]; then
|
||||
rm /tmp/smswakeup$CURRMODEM
|
||||
n=$(( $n + $SLEEP ))
|
||||
else
|
||||
n=$(( $n + 1 ))
|
||||
fi
|
||||
done
|
||||
done
|
41
rooter/0basicsupport/ext-sms/files/usr/lib/sms/sendsms.lua
Normal file
41
rooter/0basicsupport/ext-sms/files/usr/lib/sms/sendsms.lua
Normal file
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/lua
|
||||
|
||||
modem = arg[1]
|
||||
addr = arg[2]
|
||||
dcs = arg[3]
|
||||
txt = arg[4]
|
||||
suffix = arg[5]
|
||||
|
||||
if package.path:find(";/usr/lib/sms/?.lua") == nil then
|
||||
package.path = package.path .. ";/usr/lib/sms/?.lua"
|
||||
end
|
||||
|
||||
local pack7bit = require "pack7bit"
|
||||
|
||||
udl = string.format("%02X", math.floor(#txt / 2))
|
||||
da = "81"
|
||||
if addr:sub(1, 1) == "+" then
|
||||
da = "91"
|
||||
addr = addr:sub(2)
|
||||
elseif addr:sub(1, 1) == "-" then
|
||||
addr = addr:sub(2)
|
||||
end
|
||||
da = string.format("%02X", #addr) .. da
|
||||
if (#addr % 2) > 0 then
|
||||
addr = addr .. "F"
|
||||
end
|
||||
k = #addr
|
||||
j = 1
|
||||
repeat
|
||||
da = da .. addr:sub(j + 1, j + 1) .. addr:sub(j, j)
|
||||
j = j + 2
|
||||
until j > k
|
||||
if dcs == "00" then
|
||||
pack7bit.pack(udl, txt)
|
||||
ud = pack7bit["pdu"]
|
||||
else
|
||||
ud = txt
|
||||
end
|
||||
pdu = "001100" .. da .. "00" .. dcs .. "AD" .. udl .. ud
|
||||
pdul = string.format("%03d", (math.floor(#pdu / 2) - 1))
|
||||
os.execute("/usr/lib/sms/sendsms.sh " .. modem .. " " .. pdul .. "," .. suffix .. "," .. pdu .. " &")
|
10
rooter/0basicsupport/ext-sms/files/usr/lib/sms/sendsms.sh
Normal file
10
rooter/0basicsupport/ext-sms/files/usr/lib/sms/sendsms.sh
Normal file
@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
ROOTER=/usr/lib/rooter
|
||||
|
||||
CURRMODEM=$1
|
||||
ATCMDD=$2
|
||||
|
||||
COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport)
|
||||
|
||||
OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "sendsms-at.gcom" "$CURRMODEM" "$ATCMDD")
|
24
rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsout.lua
Normal file
24
rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsout.lua
Normal file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/lua
|
||||
|
||||
local modem = arg[1]
|
||||
local dest = arg[2]
|
||||
local txt = arg[3]
|
||||
local pid = arg[4]
|
||||
local rfname = "/tmp/smssendstatus" .. pid
|
||||
|
||||
if package.path:find(";/usr/lib/sms/?.lua") == nil then
|
||||
package.path = package.path .. ";/usr/lib/sms/?.lua"
|
||||
end
|
||||
|
||||
local utf8togsm = require "utf8togsm"
|
||||
utf8togsm.chktxt(txt)
|
||||
local msg = utf8togsm["msg"]
|
||||
local dcs = utf8togsm["dcs"]
|
||||
txt = utf8togsm["txt"]
|
||||
|
||||
if msg == nil then
|
||||
os.execute("if [ -e " .. rfname .. " ]; then rm " ..rfname .. "; fi")
|
||||
os.execute("lua /usr/lib/sms/sendsms.lua " .. modem .. " " .. dest .. " " .. dcs .. " " .. txt .. " " .. pid)
|
||||
else
|
||||
os.execute('echo "SMS sending failed - text is too long" > ' .. rfname)
|
||||
end
|
38
rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsout.sh
Normal file
38
rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsout.sh
Normal file
@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
|
||||
ROOTER=/usr/lib/rooter
|
||||
|
||||
log() {
|
||||
logger -t "sms process" "$@"
|
||||
}
|
||||
|
||||
CURRMODEM=$(uci get modem.general.smsnum)
|
||||
|
||||
DEST="$1"
|
||||
shift 1
|
||||
TXT="$@"
|
||||
MYPID=$(printf "%05d" $$)
|
||||
MYPID=$(printf "${MYPID:1:4}")
|
||||
RESFILE="/tmp/smssendstatus"$MYPID
|
||||
|
||||
lua /usr/lib/sms/smsout.lua $CURRMODEM $DEST "$TXT" $MYPID
|
||||
sleep 5
|
||||
COUNT=0
|
||||
XSTATUS=1
|
||||
RES="SMS sending failed, timeout reading result"
|
||||
while [ $COUNT -lt 15 ]; do
|
||||
if [ -e $RESFILE ]; then
|
||||
read RES < $RESFILE
|
||||
if [ "${RES:0:9}" = "SMS sent," ]; then
|
||||
XSTATUS=0
|
||||
fi
|
||||
COUNT=999
|
||||
rm $RESFILE
|
||||
else
|
||||
sleep 2
|
||||
fi
|
||||
COUNT=$(($COUNT + 1))
|
||||
done
|
||||
log "$RES"
|
||||
echo "$RES"
|
||||
exit $XSTATUS
|
862
rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsread.lua
Normal file
862
rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsread.lua
Normal file
@ -0,0 +1,862 @@
|
||||
#!/usr/bin/lua
|
||||
|
||||
senders2delete = {}
|
||||
deletebinaries = false
|
||||
|
||||
modemn = arg[1]
|
||||
|
||||
local smsresult = "/tmp/smsresult" .. modemn .. ".at"
|
||||
local smsslots = "/tmp/smsslots" .. modemn
|
||||
local smstime = "/tmp/smstime" .. modemn
|
||||
local t = {}
|
||||
local tptr
|
||||
local m_pdu_ptr
|
||||
local m_pdu
|
||||
local m_smsc
|
||||
local m_with_udh
|
||||
local m_report
|
||||
local m_number
|
||||
local m_replace
|
||||
local m_alphabet
|
||||
local m_dcs
|
||||
local m_flash
|
||||
local m_date
|
||||
local m_time
|
||||
local m_text
|
||||
local m_concat
|
||||
local m_read
|
||||
local m_index
|
||||
local g_table1 = {}
|
||||
local g_table2 = {}
|
||||
|
||||
local max_smsc = 64
|
||||
local max_number = 64
|
||||
local max_udh_data = 512
|
||||
surrogate = 0
|
||||
|
||||
function reset()
|
||||
m_smsc = nil
|
||||
m_with_udh = 0
|
||||
m_report = 0
|
||||
m_number = nil
|
||||
m_replace = 0
|
||||
m_alphabet = -1
|
||||
m_flash = 0
|
||||
m_date = nil
|
||||
m_time = nil
|
||||
m_text = nil
|
||||
m_concat = nil
|
||||
end
|
||||
|
||||
function hasbit(x, p)
|
||||
return x % (p + p) >= p
|
||||
end
|
||||
|
||||
function bitor(x, y)
|
||||
local p = 1; local z = 0; local limit = x > y and x or y
|
||||
while p <= limit do
|
||||
if hasbit(x, p) or hasbit(y, p) then
|
||||
z = z + p
|
||||
end
|
||||
p = p + p
|
||||
end
|
||||
return z
|
||||
end
|
||||
|
||||
function bitand(x, y)
|
||||
local p = 1; local z = 0; local limit = x > y and x or y
|
||||
while p <= limit do
|
||||
if hasbit(x, p) and hasbit(y, p) then
|
||||
z = z + p
|
||||
end
|
||||
p = p + p
|
||||
end
|
||||
return z
|
||||
end
|
||||
|
||||
function bitright(x, y)
|
||||
return math.floor(x / 2 ^ y)
|
||||
end
|
||||
|
||||
function bitleft(x, y)
|
||||
return x * 2 ^ y
|
||||
end
|
||||
|
||||
function ocount(x, y)
|
||||
local j = 0
|
||||
local i = x:find(y, 0)
|
||||
while i ~= nil do
|
||||
i = x:find(y, i + 1)
|
||||
j = j + 1
|
||||
end
|
||||
return j
|
||||
end
|
||||
|
||||
printf = function(s,...)
|
||||
if echo == 0 then
|
||||
io.write(s:format(...))
|
||||
else
|
||||
ss = s:format(...)
|
||||
os.execute("/usr/lib/rooter/logprint.sh " .. ss)
|
||||
end
|
||||
end
|
||||
|
||||
function isxdigit(digit)
|
||||
if digit == nil then
|
||||
return 0
|
||||
end
|
||||
if digit >= 48 and digit <= 57 then
|
||||
return 1
|
||||
end
|
||||
if digit >= 97 and digit <= 102 then
|
||||
return 1
|
||||
end
|
||||
if digit >= 65 and digit <= 70 then
|
||||
return 1
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function isdigit(digit)
|
||||
if digit >= 48 and digit <= 57 then
|
||||
return 1
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function octet2bin(octet)
|
||||
result = 0
|
||||
if octet:byte(1) > 57 then
|
||||
result = result + octet:byte(1) - 55
|
||||
else
|
||||
result = result + octet:byte(1) - 48
|
||||
end
|
||||
result = result * 16
|
||||
if octet:byte(2) > 57 then
|
||||
result = result + octet:byte(2) - 55
|
||||
else
|
||||
result = result + octet:byte(2) - 48
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function octet2bin_check(octet)
|
||||
if octet:byte(1) == 0 then
|
||||
return -1
|
||||
end
|
||||
if octet:byte(2) == 0 then
|
||||
return -2
|
||||
end
|
||||
if isxdigit(octet:byte(1)) == 0 then
|
||||
return -3
|
||||
end
|
||||
if isxdigit(octet:byte(2)) == 0 then
|
||||
return -4
|
||||
end
|
||||
return octet2bin(octet)
|
||||
end
|
||||
|
||||
function swapchars(sstring)
|
||||
local length = sstring:len()
|
||||
local xstring = nil
|
||||
local i = 1
|
||||
while i < length do
|
||||
c1 = sstring:sub(i, i)
|
||||
c2 = sstring:sub(i+1, i+1)
|
||||
if xstring == nil then
|
||||
xstring = c2 .. c1
|
||||
else
|
||||
xstring = xstring .. c2 .. c1
|
||||
end
|
||||
i = i + 2
|
||||
end
|
||||
return xstring
|
||||
end
|
||||
|
||||
function parseSMSC()
|
||||
m_pdu_ptr = m_pdu
|
||||
local length = octet2bin_check(m_pdu_ptr)
|
||||
if length < 0 then
|
||||
return -1
|
||||
end
|
||||
if length == 0 then
|
||||
m_smsc = ""
|
||||
m_pdu_ptr = m_pdu_ptr:sub(3)
|
||||
return 1
|
||||
end
|
||||
if length < 2 or length > max_smsc then
|
||||
return -1
|
||||
end
|
||||
length = (length * 2) - 2
|
||||
local mlen = m_pdu:len()
|
||||
if mlen < (length + 4) then
|
||||
return -1
|
||||
end
|
||||
m_pdu_ptr = m_pdu_ptr:sub(3)
|
||||
local addr_type = octet2bin_check(m_pdu_ptr)
|
||||
if addr_type < 0 then
|
||||
return -1
|
||||
end
|
||||
if addr_type < 0x80 then
|
||||
return -1
|
||||
end
|
||||
m_pdu_ptr = m_pdu_ptr:sub(3)
|
||||
m_smsc = m_pdu_ptr:sub(0, length)
|
||||
m_smsc = swapchars(m_smsc)
|
||||
if addr_type < 0x90 then
|
||||
for j=1, length do
|
||||
if isxdigit(m_smsc:byte(j)) == 0 then
|
||||
return -1
|
||||
end
|
||||
end
|
||||
else
|
||||
if m_smsc:byte(length) == 70 then
|
||||
m_smsc = m_smsc:sub(1, length-1)
|
||||
end
|
||||
local leng = m_smsc:len()
|
||||
for j=1,leng do
|
||||
if isdigit(m_smsc:byte(j)) == 0 then
|
||||
return -1
|
||||
end
|
||||
end
|
||||
end
|
||||
m_pdu_ptr = m_pdu_ptr:sub(length + 1)
|
||||
return 1
|
||||
end
|
||||
|
||||
function explainAddressType(octet_char, octet_int)
|
||||
local result
|
||||
if octet_char ~= nil then
|
||||
result = octet2bin_check(octet_char)
|
||||
else
|
||||
result = octet_int
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function concatinfo(x)
|
||||
while #x > 9 do
|
||||
if x:sub(1, 4) == '0003' then
|
||||
if x:sub(7, 10) ~= '0101' then
|
||||
m_concat = 'Msg# ' .. tonumber(x:sub(5, 6), 16)
|
||||
m_concat = m_concat .. ',' .. tonumber(x:sub(9, 10), 16)
|
||||
m_concat = m_concat .. '/' .. tonumber(x:sub(7, 8), 16)
|
||||
end
|
||||
x = ""
|
||||
elseif x:sub(1, 4) == '0804' then
|
||||
if x:sub(9, 12) ~= '0101' then
|
||||
m_concat = 'Msg# ' .. tonumber(x:sub(5, 8), 16)
|
||||
m_concat = m_concat .. ',' .. tonumber(x:sub(11, 12), 16)
|
||||
m_concat = m_concat .. '/' .. tonumber(x:sub(9, 10), 16)
|
||||
end
|
||||
x = ""
|
||||
else
|
||||
local iel = tonumber(x:sub(3, 4), 16)
|
||||
x = x:sub(5 + iel * 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function pdu2binary(pdu, with_udh)
|
||||
local skip_octets = 0
|
||||
local octetcounter
|
||||
m_text = ''
|
||||
local octets = octet2bin_check(pdu)
|
||||
local last_i = 0
|
||||
if octets < 0 then
|
||||
return -1
|
||||
end
|
||||
if with_udh > 0 then
|
||||
local pdu2 = pdu:sub(3)
|
||||
local udhl = tonumber(pdu2:sub(1, 2), 16)
|
||||
concatinfo(pdu2:sub(3, (udhl + 1) * 2))
|
||||
local udhsize = octet2bin_check(pdu2)
|
||||
if udhsize < 0 then
|
||||
return -1
|
||||
end
|
||||
skip_octets = udhsize + 1
|
||||
end
|
||||
for octetcounter = 0, (octets - skip_octets - 1) do
|
||||
local pdu2 = pdu:sub((octetcounter * 2) + 3 + (skip_octets * 2))
|
||||
local i = octet2bin_check(pdu2)
|
||||
if i < 0 then
|
||||
return -1
|
||||
end
|
||||
if m_alphabet == 2 then
|
||||
if (2 + octetcounter) % 2 == 0 then
|
||||
last_i = i
|
||||
else
|
||||
m_text = word2utf8(bitor(bitleft(last_i, 8), i), m_text)
|
||||
end
|
||||
else
|
||||
if i < 32 or i > 127 then
|
||||
i = 0x25A1
|
||||
end
|
||||
m_text = word2utf8(i, m_text)
|
||||
end
|
||||
end
|
||||
return (octets - skip_octets)
|
||||
end
|
||||
|
||||
function pdu2text(pdu, with_udh)
|
||||
local result
|
||||
local octetcounter
|
||||
local skip_characters = 0
|
||||
local binary = 0
|
||||
m_text = ''
|
||||
local septets = octet2bin_check(pdu)
|
||||
if septets < 0 then
|
||||
return -1
|
||||
end
|
||||
if with_udh > 0 then
|
||||
local pdu2 = pdu:sub(3)
|
||||
local udhl = tonumber(pdu2:sub(1, 2), 16)
|
||||
concatinfo(pdu2:sub(3, (udhl + 1) * 2))
|
||||
local udhsize = octet2bin_check(pdu2)
|
||||
skip_characters = math.floor((((udhsize+1)*8)+6)/7)
|
||||
end
|
||||
local octets = math.floor((septets * 7 + 7) / 8)
|
||||
local bitposition = 0
|
||||
local byteposition
|
||||
local byteoffset
|
||||
local i
|
||||
local g_table_nbr = 1
|
||||
octetcounter = 0
|
||||
for charcounter=0,septets-1 do
|
||||
local c = 0
|
||||
for bitcounter=0,6 do
|
||||
byteposition = math.floor(bitposition / 8)
|
||||
byteoffset = bitposition % 8
|
||||
while (byteposition >= octetcounter) and (octetcounter < octets) do
|
||||
local pdu2 = pdu:sub((octetcounter * 2) + 3)
|
||||
i = octet2bin_check(pdu2)
|
||||
if i < 0 then
|
||||
return -2
|
||||
end
|
||||
binary = i
|
||||
octetcounter = octetcounter + 1
|
||||
end
|
||||
if bitand(binary, (2^byteoffset)) > 0 then
|
||||
c = bitor(c, 128)
|
||||
end
|
||||
bitposition = bitposition + 1
|
||||
c = bitand(math.floor(c / 2), 127)
|
||||
end
|
||||
c = gsm2byte(c)
|
||||
if charcounter >= skip_characters and c ~= 27 then
|
||||
m_text = word2utf8(c, m_text)
|
||||
end
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
function gsm2byte(ch)
|
||||
if g_table_nbr == 2 then
|
||||
if g_table2[ch] == nil then
|
||||
ch = 63
|
||||
else
|
||||
ch = g_table2[ch]
|
||||
end
|
||||
g_table_nbr = 1
|
||||
else
|
||||
if ch == 27 then
|
||||
g_table_nbr = 2
|
||||
else
|
||||
if g_table1[ch] ~= nil then
|
||||
ch = g_table1[ch]
|
||||
end
|
||||
end
|
||||
end
|
||||
return ch
|
||||
end
|
||||
|
||||
function word2utf8(i, txt)
|
||||
if surrogate > 0 then
|
||||
if i >= 0xDC00 and i <= 0xDFFF then
|
||||
local ii = 0x10000 + bitand(i, 0x3FF) + bitleft(bitand(surrogate, 0x3FF), 10)
|
||||
txt = txt .. string.char(bitor(0xF0, bitright(bitand(ii, 0x1C0000), 18)))
|
||||
txt = txt .. string.char(bitor(0x80, bitright(bitand(ii, 0x3F000), 12)))
|
||||
txt = txt .. string.char(bitor(0x80, bitright(bitand(ii, 0xFC0), 6)))
|
||||
txt = txt .. string.char(bitor(0x80, bitand(ii, 0x3F)))
|
||||
else
|
||||
txt = txt .. string.char(0xe2) .. string.char(0x96) .. string.char(0xa1)
|
||||
end
|
||||
surrogate = 0
|
||||
elseif i >= 0xD800 and i <= 0xDBFF then
|
||||
surrogate = i
|
||||
elseif i >= 0xDC00 and i <= 0xDFFF then
|
||||
txt = txt .. string.char(0xe2) .. string.char(0x96) .. string.char(0xa1)
|
||||
elseif i < 0x80 then
|
||||
txt = txt .. string.char(i)
|
||||
elseif i < 0x800 then
|
||||
txt = txt .. string.char(bitor(0xC0, bitright(bitand(i, 0x7C0), 6)))
|
||||
txt = txt .. string.char(bitor(0x80, bitand(i, 0x3F)))
|
||||
else
|
||||
if i == 0x2029 then
|
||||
txt = txt .. string.char(10)
|
||||
else
|
||||
txt = txt .. string.char(bitor(0xE0, bitright(bitand(i, 0xF000), 12)))
|
||||
txt = txt .. string.char(bitor(0x80, bitright(bitand(i, 0xFC0), 6)))
|
||||
txt = txt .. string.char(bitor(0x80, bitand(i, 0x3F)))
|
||||
end
|
||||
end
|
||||
return txt
|
||||
end
|
||||
|
||||
function parseDeliver()
|
||||
if m_pdu_ptr:len() < 4 then
|
||||
return 0
|
||||
end
|
||||
local padding = 0
|
||||
local length = octet2bin_check(m_pdu_ptr)
|
||||
local timezone
|
||||
if length < 0 or length > max_number then
|
||||
return 0
|
||||
end
|
||||
-- Sender Address
|
||||
if length == 0 then
|
||||
m_pdu_ptr = m_pdu_ptr:sub(5)
|
||||
else
|
||||
padding = length % 2
|
||||
m_pdu_ptr = m_pdu_ptr:sub(3)
|
||||
local addr_type = explainAddressType(m_pdu_ptr, 0)
|
||||
if addr_type < 0 then
|
||||
return 0
|
||||
end
|
||||
if addr_type < 0x80 then
|
||||
return 0
|
||||
end
|
||||
m_pdu_ptr = m_pdu_ptr:sub(3)
|
||||
if bitand(addr_type, 112) == 80 then
|
||||
if m_pdu_ptr:len() < (length + padding) then
|
||||
return 0
|
||||
end
|
||||
local htmp = string.format("%x", math.floor((length * 4) / 7))
|
||||
if htmp:len() < 2 then
|
||||
htmp = "0" .. htmp
|
||||
end
|
||||
htmp = htmp:upper()
|
||||
local tpdu = htmp .. m_pdu_ptr
|
||||
local res = pdu2text(tpdu, 0)
|
||||
if res < 0 then
|
||||
return 0
|
||||
end
|
||||
m_number = string.gsub(m_text, "\n", " ")
|
||||
m_text = nil
|
||||
else
|
||||
m_number = m_pdu_ptr:sub(1, length + padding + 1)
|
||||
m_number = swapchars(m_number)
|
||||
if m_number:byte(length + padding) == 70 then
|
||||
m_number = m_number:sub(1, length + padding - 1)
|
||||
end
|
||||
if addr_type == 145 then
|
||||
m_number = "+" .. m_number
|
||||
end
|
||||
end
|
||||
end
|
||||
m_pdu_ptr = m_pdu_ptr:sub(length + padding + 1)
|
||||
if m_pdu_ptr:len() < 20 then
|
||||
return 0
|
||||
end
|
||||
-- PID
|
||||
local byte_buf = octet2bin_check(m_pdu_ptr)
|
||||
if byte_buf < 0 then
|
||||
return 0
|
||||
end
|
||||
if bitand(byte_buf, 0xF8) == 0x40 then
|
||||
m_replace = bitand(byte_buf, 0x07)
|
||||
end
|
||||
m_pdu_ptr = m_pdu_ptr:sub(3)
|
||||
-- Alphabet
|
||||
byte_buf = octet2bin_check(m_pdu_ptr)
|
||||
if byte_buf < 0 then
|
||||
return 0
|
||||
end
|
||||
m_alphabet = math.floor(bitand(byte_buf, 0x0C) / 4)
|
||||
if m_alphabet == 3 then
|
||||
return 0
|
||||
end
|
||||
if m_alphabet == 0 then
|
||||
m_alphabet = -1
|
||||
end
|
||||
-- DCS, Flash Msg
|
||||
m_dcs = byte_buf
|
||||
if bitand(byte_buf, 0x10) > 0 then
|
||||
if bitand(byte_buf, 0x01) > 0 then
|
||||
m_flash = 1
|
||||
end
|
||||
end
|
||||
m_pdu_ptr = m_pdu_ptr:sub(3)
|
||||
-- Date
|
||||
local str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. "-" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. "-" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5)
|
||||
if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then
|
||||
return 0
|
||||
end
|
||||
m_date = str_buf
|
||||
m_pdu_ptr = m_pdu_ptr:sub(7)
|
||||
-- Time
|
||||
str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. ":" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. ":" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5)
|
||||
if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then
|
||||
return 0
|
||||
end
|
||||
if tonumber(m_pdu_ptr:sub(8,8), 16) > 7 then
|
||||
timezone = '-' .. ((tonumber(m_pdu_ptr:sub(8, 8), 16) - 8) .. tonumber(m_pdu_ptr:sub(7, 7), 16)) / 4
|
||||
else
|
||||
timezone = '+' .. (m_pdu_ptr:sub(8, 8) .. tonumber(m_pdu_ptr:sub(7, 7), 16)) / 4
|
||||
end
|
||||
if timezone:sub(-2, -1) == '.0' then
|
||||
timezone = timezone:sub(1, -3)
|
||||
end
|
||||
m_time = str_buf .. ' ' .. timezone .. 'h'
|
||||
m_pdu_ptr = m_pdu_ptr:sub(7)
|
||||
if octet2bin_check(m_pdu_ptr) < 0 then
|
||||
return 0
|
||||
end
|
||||
m_pdu_ptr = m_pdu_ptr:sub(3)
|
||||
|
||||
-- Text
|
||||
local result = 0
|
||||
local bin_udh = 1
|
||||
if m_alphabet <= 0 then
|
||||
result = pdu2text(m_pdu_ptr, m_with_udh)
|
||||
return result
|
||||
else
|
||||
result = pdu2binary(m_pdu_ptr, m_with_udh)
|
||||
return result
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
function parseStatusReport()
|
||||
if m_pdu_ptr:len() < 6 then
|
||||
return 0
|
||||
end
|
||||
local messageid = octet2bin_check(m_pdu_ptr)
|
||||
if messageid < 0 then
|
||||
return 0
|
||||
end
|
||||
m_pdu_ptr = m_pdu_ptr:sub(3)
|
||||
local length = octet2bin_check(m_pdu_ptr)
|
||||
if length < 1 or length > max_number then
|
||||
return 0
|
||||
end
|
||||
local padding = length % 2
|
||||
m_pdu_ptr = m_pdu_ptr:sub(3)
|
||||
local addr_type = explainAddressType(m_pdu_ptr, 0)
|
||||
if addr_type < 0x80 then
|
||||
return 0
|
||||
end
|
||||
m_pdu_ptr = m_pdu_ptr:sub(3)
|
||||
if bitand(addr_type, 112) == 80 then
|
||||
if m_pdu_ptr:len() < (length + padding) then
|
||||
return 0
|
||||
end
|
||||
local htmp = string.format("%x", math.floor((length * 4) / 7))
|
||||
if htmp:len() < 2 then
|
||||
htmp = "0" .. htmp
|
||||
end
|
||||
local tpdu = htmp .. m_pdu_ptr
|
||||
local res = pdu2text(tpdu, 0)
|
||||
if res < 0 then
|
||||
return 0
|
||||
end
|
||||
m_number = m_text
|
||||
m_text = nil
|
||||
else
|
||||
m_number = m_pdu_ptr:sub(1, length + padding + 1)
|
||||
m_number = swapchars(m_number)
|
||||
if m_number:byte(length + padding) == 70 then
|
||||
m_number = m_number:sub(1, length + padding - 1)
|
||||
end
|
||||
end
|
||||
m_pdu_ptr = m_pdu_ptr:sub(length + padding + 1)
|
||||
if m_pdu_ptr:len() < 14 then
|
||||
return 0
|
||||
end
|
||||
-- Date
|
||||
local str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. "-" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. "-" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5)
|
||||
if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then
|
||||
return 0
|
||||
end
|
||||
m_date = str_buf
|
||||
m_pdu_ptr = m_pdu_ptr:sub(7)
|
||||
-- Time
|
||||
str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. ":" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. ":" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5)
|
||||
if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then
|
||||
return 0
|
||||
end
|
||||
m_time = str_buf
|
||||
m_pdu_ptr = m_pdu_ptr:sub(7)
|
||||
if octet2bin_check(m_pdu_ptr) < 0 then
|
||||
return 0
|
||||
end
|
||||
m_pdu_ptr = m_pdu_ptr:sub(3)
|
||||
-- Discharge Date
|
||||
local str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. "-" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. "-" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5)
|
||||
if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then
|
||||
return 0
|
||||
end
|
||||
local d_date = str_buf
|
||||
m_pdu_ptr = m_pdu_ptr:sub(7)
|
||||
-- Time
|
||||
str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. ":" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. ":" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5)
|
||||
if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then
|
||||
return 0
|
||||
end
|
||||
local d_time = str_buf
|
||||
m_pdu_ptr = m_pdu_ptr:sub(7)
|
||||
if octet2bin_check(m_pdu_ptr) < 0 then
|
||||
return 0
|
||||
end
|
||||
m_pdu_ptr = m_pdu_ptr:sub(3)
|
||||
local status = octet2bin_check(m_pdu_ptr)
|
||||
if status < 0 then
|
||||
return 0
|
||||
end
|
||||
m_text = string.format("Discharge Timestamp: %s %s Message ID: %d Status: %d", d_date, d_time, messageid, status)
|
||||
return 1
|
||||
end
|
||||
|
||||
function parse()
|
||||
local flag = parseSMSC()
|
||||
if flag ~= 1 then
|
||||
return 0
|
||||
end
|
||||
local tmp = octet2bin_check(m_pdu_ptr)
|
||||
if tmp < 0 then
|
||||
return 0
|
||||
end
|
||||
if bitand(tmp, 0x40) > 0 then
|
||||
m_with_udh = 1
|
||||
end
|
||||
if bitand(tmp, 0x20) > 0 then
|
||||
m_report = 1
|
||||
end
|
||||
local type = bitand(tmp, 3)
|
||||
if type == 0 then
|
||||
m_pdu_ptr = m_pdu_ptr:sub(3)
|
||||
local result = parseDeliver()
|
||||
if result < 1 then
|
||||
return 0
|
||||
end
|
||||
else
|
||||
if type == 2 then
|
||||
m_pdu_ptr = m_pdu_ptr:sub(3)
|
||||
local result = parseStatusReport()
|
||||
return result
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
function trim(s)
|
||||
return (s:gsub("^%s*(.-)%s*$", "%1"))
|
||||
end
|
||||
|
||||
function readpdu(pdu)
|
||||
m_pdu = pdu
|
||||
m_pdu_ptr = m_pdu
|
||||
reset()
|
||||
local flag = parse()
|
||||
if flag > 0 then
|
||||
t[tptr] = m_index
|
||||
t[tptr+1] = m_read
|
||||
t[tptr+2] = m_number
|
||||
if string.find(delsend, gschar .. m_number .. gschar, 1, true) then
|
||||
delslots = delslots .. m_index .. " "
|
||||
else
|
||||
if m_dcs == 245 and deletebinaries then
|
||||
delslots = delslots .. m_index .. " "
|
||||
end
|
||||
end
|
||||
t[tptr+3] = m_date
|
||||
t[tptr+4] = m_time
|
||||
if m_concat ~= nil then
|
||||
m_text = m_concat .. '\n' .. m_text
|
||||
end
|
||||
t[tptr+5] = m_text
|
||||
tptr = tptr + 6
|
||||
end
|
||||
end
|
||||
|
||||
local max_msg = "0"
|
||||
local used_msg = "0"
|
||||
gschar = string.char(29)
|
||||
delsend = gschar .. table.concat(senders2delete, gschar) .. gschar
|
||||
delslots = ""
|
||||
tptr = 3
|
||||
t[1] = used_msg
|
||||
t[2] = max_msg
|
||||
g_table1 = {163, 36, 165, 232, 233, 249, 236, 242, 199, 10, 216, 248, 13, 197, 229, 0x394, 95, 0x3A6, 0x393, 0x39B, 0x3A9, 0x3A0, 0x3A8, 0x3A3, 0x398, 0x39E}
|
||||
g_table1[0] = 64
|
||||
g_table1[28] = 198
|
||||
g_table1[29] = 230
|
||||
g_table1[30] = 223
|
||||
g_table1[31] = 201
|
||||
g_table1[36] = 164
|
||||
g_table1[64] = 161
|
||||
g_table1[91] = 196
|
||||
g_table1[92] = 214
|
||||
g_table1[93] = 209
|
||||
g_table1[94] = 220
|
||||
g_table1[95] = 167
|
||||
g_table1[96] = 191
|
||||
g_table1[123] = 228
|
||||
g_table1[124] = 246
|
||||
g_table1[125] = 241
|
||||
g_table1[126] = 252
|
||||
g_table1[127] = 224
|
||||
g_table2[10] = 10
|
||||
g_table2[20] = 94
|
||||
g_table2[40] = 123
|
||||
g_table2[41] = 125
|
||||
g_table2[47] = 92
|
||||
g_table2[60] = 91
|
||||
g_table2[61] = 126
|
||||
g_table2[62] = 93
|
||||
g_table2[64] = 124
|
||||
g_table2[101] = 0x20AC
|
||||
--
|
||||
os.execute("touch " .. smsslots)
|
||||
local slottab = {}
|
||||
local file = io.open(smsslots, "r")
|
||||
for k in file:lines() do
|
||||
slottab[k] = true
|
||||
end
|
||||
file:close()
|
||||
local file = io.open(smsresult, "r")
|
||||
local m_r = ""
|
||||
if file ~= nil then
|
||||
repeat
|
||||
local s, e, cs, ce, ms, me
|
||||
local line = file:read("*l")
|
||||
if line == nil then
|
||||
break
|
||||
end
|
||||
s, e = line:find("+CPMS:")
|
||||
if s ~= nil then
|
||||
cs, ce = line:find(",", e)
|
||||
if cs ~= nil then
|
||||
used_msg = trim(line:sub(e+1, cs-1))
|
||||
t[1] = used_msg
|
||||
ms, me = line:find(",", ce+1)
|
||||
if ms ~= nil then
|
||||
max_msg = trim(line:sub(ce+1, ms-1))
|
||||
t[2] = max_msg
|
||||
end
|
||||
end
|
||||
line = file:read("*l")
|
||||
if line == nil then
|
||||
break
|
||||
end
|
||||
end
|
||||
s, e = line:find("+CMGL:")
|
||||
if s ~= nil then
|
||||
m_index = "0"
|
||||
cs, ce = line:find(",", e)
|
||||
if cs ~= nil then
|
||||
m_index = trim(line:sub(e+1, cs-1))
|
||||
end
|
||||
ds, de = line:find(",", ce+1)
|
||||
if ds ~= nil then
|
||||
surrogate = 0
|
||||
m_r = trim(line:sub(ce+1, ds-1))
|
||||
if m_r == "0" then
|
||||
m_read = word2utf8(0x2691, word2utf8(0x2691, ''))
|
||||
os.execute("date +%s > " .. smstime)
|
||||
if not slottab[m_index] then
|
||||
os.execute("echo " .. m_index .. " >> " .. smsslots)
|
||||
end
|
||||
elseif slottab[m_index] then
|
||||
m_read = word2utf8(0x2691, ' ')
|
||||
else
|
||||
m_read = word2utf8(0x2713, ' ')
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
line = file:read("*l")
|
||||
if line == nil then
|
||||
break
|
||||
end
|
||||
readpdu(line)
|
||||
if m_r == "0" then
|
||||
if m_text == "::reboot!!" then
|
||||
os.execute("(sleep 60; reboot -f) &")
|
||||
elseif m_text == "::pwrtoggle!!" then
|
||||
os.execute("(sleep 60; /usr/lib/rooter/pwrtoggle.sh 3) &")
|
||||
elseif m_text:sub(1, 3) == "GPS" then
|
||||
cmd_hand = io.popen("uci -q get modem.general.pin")
|
||||
gpspin = cmd_hand:read()
|
||||
cmd_hand:close()
|
||||
if (m_text == "GPS" and gpspin == nil) or (m_text == "GPS " .. gpspin) then
|
||||
if tonumber(m_number) ~= nil then
|
||||
os.execute("/usr/lib/gps/smsreply.sh " .. modemn .. " " .. m_number .. "&")
|
||||
delslots = delslots .. m_index .. " "
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
until 1==0
|
||||
file:close()
|
||||
end
|
||||
|
||||
local tfname = "/tmp/smstemptext" .. math.random(99)
|
||||
local tfile = io.open(tfname, "w")
|
||||
tfile:write(t[1] .. "\n")
|
||||
tfile:write(t[2] .. "\n")
|
||||
if tonumber(used_msg) == 0 then
|
||||
tfile:close()
|
||||
else
|
||||
i = 3
|
||||
while t[i] ~= nil do
|
||||
local mtxt = t[i + 5]
|
||||
tfile:write(t[i] .. "\n")
|
||||
tfile:write(t[i + 2] .. "\n")
|
||||
tfile:write((ocount(mtxt, '\n') + 1) .. '\n')
|
||||
tfile:write(mtxt .. "\n")
|
||||
local mn = t[i + 2] .. " "
|
||||
mn = mn:sub(1,20)
|
||||
local stxt = ''
|
||||
local j = 0
|
||||
local k = 1
|
||||
local ch = ''
|
||||
while j < 20 do
|
||||
ch = string.byte(mtxt:sub(k, k))
|
||||
if ch == nil then
|
||||
j = 20
|
||||
elseif ch == 10 or ch == 13 then
|
||||
stxt = stxt .. ' '
|
||||
k = k + 1
|
||||
elseif ch < 127 then
|
||||
stxt = stxt .. string.char(ch)
|
||||
k = k + 1
|
||||
elseif ch < 0xE0 then
|
||||
stxt = stxt .. mtxt:sub(k, k + 1)
|
||||
k = k + 2
|
||||
elseif ch < 0xF0 then
|
||||
stxt = stxt .. mtxt:sub(k, k + 2)
|
||||
k = k + 3
|
||||
else
|
||||
stxt = stxt .. mtxt:sub(k, k + 3)
|
||||
k = k + 4
|
||||
end
|
||||
j = j + 1
|
||||
end
|
||||
if mtxt ~= stxt then
|
||||
stxt = stxt .. " ..."
|
||||
end
|
||||
local msg = t[i + 1] .. " " .. mn .. t[i + 3] .. " " .. t[i + 4] .. " " .. stxt
|
||||
tfile:write(msg .. "\n")
|
||||
i = i + 6
|
||||
end
|
||||
tfile:close()
|
||||
end
|
||||
os.execute("mv " .. tfname .. " /tmp/smstext" .. modemn)
|
||||
|
||||
if #delslots > 0 then
|
||||
os.execute("/usr/lib/sms/delsms.sh " .. modemn .. " " .. delslots .. " &")
|
||||
end
|
82
rooter/0basicsupport/ext-sms/files/usr/lib/sms/sys2sms.lua
Normal file
82
rooter/0basicsupport/ext-sms/files/usr/lib/sms/sys2sms.lua
Normal file
@ -0,0 +1,82 @@
|
||||
#!/usr/bin/lua
|
||||
|
||||
local oaddr = arg[1]
|
||||
local txt = arg[2]
|
||||
local pid = arg[3]
|
||||
|
||||
if package.path:find(";/usr/lib/sms/?.lua") == nil then
|
||||
package.path = package.path .. ";/usr/lib/sms/?.lua"
|
||||
end
|
||||
|
||||
local utf8togsm = require "utf8togsm"
|
||||
local pack7bit = require "pack7bit"
|
||||
|
||||
local isok = true
|
||||
|
||||
if #oaddr > 11 then
|
||||
txt = oaddr .. " " .. txt
|
||||
oaddr = "ROOter"
|
||||
end
|
||||
|
||||
if #txt == 0 then
|
||||
txt = "Usage: /usr/lib/sms/sys2sms.sh 'from' 'text to write here'"
|
||||
end
|
||||
|
||||
utf8togsm.chktxt(txt)
|
||||
local msg = utf8togsm["msg"]
|
||||
local dcs = utf8togsm["dcs"]
|
||||
local ud = utf8togsm["txt"]
|
||||
|
||||
local udl = string.format("%02X", math.floor(#ud / 2))
|
||||
|
||||
if msg ~= nil then
|
||||
isok = false
|
||||
end
|
||||
|
||||
if isok and dcs == "00" then
|
||||
pack7bit.pack(udl, ud)
|
||||
ud = pack7bit["pdu"]
|
||||
end
|
||||
if #oaddr == 0 or oaddr == ' ' then
|
||||
oaddr = "ROOter"
|
||||
end
|
||||
if oaddr:sub(-1) == ' ' then
|
||||
oaddr = oaddr:sub(1, -2)
|
||||
end
|
||||
local oaddrl = #oaddr * 2
|
||||
if oaddrl > 14 then
|
||||
oaddrl = oaddrl - 2
|
||||
elseif oaddrl > 6 then
|
||||
oaddrl = oaddrl - 1
|
||||
end
|
||||
oaddrl = string.format("%02X", oaddrl)
|
||||
|
||||
utf8togsm.chktxt(oaddr)
|
||||
oaddr = utf8togsm["txt"]
|
||||
|
||||
if utf8togsm["dcs"] == "08" then
|
||||
isok = false
|
||||
end
|
||||
|
||||
pack7bit.pack(string.format("%02X", math.floor(#oaddr / 2)), oaddr)
|
||||
oaddr = pack7bit["pdu"]
|
||||
|
||||
dtg = os.date("%y%m%d%H%M%S%z", os.time())
|
||||
sign = dtg:sub(13, 13)
|
||||
tz = dtg:sub(-4)
|
||||
dtgif = ''
|
||||
for j = 1, 11, 2 do
|
||||
dtgif = dtgif .. dtg:sub(j + 1, j + 1) .. dtg:sub(j, j)
|
||||
end
|
||||
tz = string.format("%02d", math.floor((tonumber(tz:sub(1, 2) * 4)) + tonumber(tz:sub(3, 4) / 15)))
|
||||
tz = tz:sub(2, 2) .. tz:sub(1, 1)
|
||||
if sign == "-" then
|
||||
tz = tz:sub(1, 1) .. string.format("%X", (tonumber(tz:sub(2, 2)) + 8))
|
||||
end
|
||||
|
||||
pdu = "0004" .. oaddrl .. "D0" .. oaddr .. "00" .. dcs .. dtgif .. tz .. udl .. ud
|
||||
|
||||
if isok then
|
||||
pdul = string.format("%03d", (math.floor(#pdu / 2) - 1))
|
||||
os.execute("echo " .. pdul .. " " .. pdu .. " > /tmp/pdu" .. pid)
|
||||
end
|
65
rooter/0basicsupport/ext-sms/files/usr/lib/sms/sys2sms.sh
Normal file
65
rooter/0basicsupport/ext-sms/files/usr/lib/sms/sys2sms.sh
Normal file
@ -0,0 +1,65 @@
|
||||
#!/bin/sh
|
||||
|
||||
ROOTER=/usr/lib/rooter
|
||||
|
||||
log() {
|
||||
logger -t "sms process" "$@"
|
||||
}
|
||||
|
||||
ADDR="$1"
|
||||
shift 1
|
||||
TXT="$@"
|
||||
MYPID=$(printf "%05d" $$)
|
||||
RESFILE="/tmp/pdu"$MYPID
|
||||
|
||||
CURRMODEM=$(uci get modem.general.smsnum)
|
||||
COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport)
|
||||
|
||||
RES=""
|
||||
XSTATUS=0
|
||||
|
||||
lua /usr/lib/sms/sys2sms.lua "$ADDR" "$TXT" $MYPID
|
||||
|
||||
if [ -e $RESFILE ]; then
|
||||
read PDUL PDU < $RESFILE
|
||||
rm $RESFILE
|
||||
else
|
||||
RES="Failed to write SMS - is text too long?"
|
||||
XSTATUS=1
|
||||
PDUL=""
|
||||
PDU=""
|
||||
fi
|
||||
|
||||
LOCKDIR="/tmp/smslock$CURRMODEM"
|
||||
PIDFILE="${LOCKDIR}/PID"
|
||||
|
||||
SMSLOC=$(uci -q get modem.modem$CURRMODEM.smsloc)
|
||||
ATCMDD="$PDUL,$SMSLOC,0,$PDU"
|
||||
|
||||
while [ $XSTATUS -eq 0 ]; do
|
||||
if mkdir "${LOCKDIR}" &>/dev/null; then
|
||||
echo "$$" > "${PIDFILE}"
|
||||
OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "smswrite.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
RES=$(echo "$OX" | grep "+CMGW:")
|
||||
if [ ${#RES} -eq 0 ]; then
|
||||
RES="Failed to write SMS - is SMS storage full?"
|
||||
XSTATUS=1
|
||||
else
|
||||
RES="New SMS written successfully"
|
||||
fi
|
||||
rm -rf "${LOCKDIR}"
|
||||
break
|
||||
else
|
||||
OTHERPID="$(cat "${PIDFILE}")"
|
||||
if [ $? = 0 ]; then
|
||||
if ! kill -0 $OTHERPID &>/dev/null; then
|
||||
rm -rf "${LOCKDIR}"
|
||||
fi
|
||||
fi
|
||||
sleep 1
|
||||
fi
|
||||
done
|
||||
|
||||
log "$RES"
|
||||
echo "$RES"
|
||||
exit $XSTATUS
|
7
rooter/0basicsupport/ext-sms/files/usr/lib/sms/toggle.sh
Normal file
7
rooter/0basicsupport/ext-sms/files/usr/lib/sms/toggle.sh
Normal file
@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
SET=$1
|
||||
|
||||
uci set modem.sms.menable=$SET
|
||||
uci commit modem
|
||||
|
167
rooter/0basicsupport/ext-sms/files/usr/lib/sms/utf8togsm.lua
Normal file
167
rooter/0basicsupport/ext-sms/files/usr/lib/sms/utf8togsm.lua
Normal file
@ -0,0 +1,167 @@
|
||||
local utf8togsm = {}
|
||||
|
||||
function hasbit(x, p)
|
||||
return x % (p + p) >= p
|
||||
end
|
||||
|
||||
function bitand(x, y)
|
||||
local p = 1; local z = 0; local limit = x > y and x or y
|
||||
while p <= limit do
|
||||
if hasbit(x, p) and hasbit(y, p) then
|
||||
z = z + p
|
||||
end
|
||||
p = p + p
|
||||
end
|
||||
return z
|
||||
end
|
||||
|
||||
function bitor(x, y)
|
||||
local p = 1; local z = 0; local limit = x > y and x or y
|
||||
while p <= limit do
|
||||
if hasbit(x, p) or hasbit(y, p) then
|
||||
z = z + p
|
||||
end
|
||||
p = p + p
|
||||
end
|
||||
return z
|
||||
end
|
||||
|
||||
function bitleft(x, y)
|
||||
return x * 2 ^ y
|
||||
end
|
||||
|
||||
function bitright(x, y)
|
||||
return math.floor(x / 2 ^ y)
|
||||
end
|
||||
|
||||
function utf8togsm.chktxt(txt)
|
||||
local g7t = {}
|
||||
g7t[64] = "00"
|
||||
g7t[163] = "01"
|
||||
g7t[36] = "02"
|
||||
g7t[165] = "03"
|
||||
g7t[232] = "04"
|
||||
g7t[233] = "05"
|
||||
g7t[249] = "06"
|
||||
g7t[236] = "07"
|
||||
g7t[242] = "08"
|
||||
g7t[199] = "09"
|
||||
g7t[216] = "0B"
|
||||
g7t[248] = "0C"
|
||||
g7t[197] = "0E"
|
||||
g7t[229] = "0F"
|
||||
g7t[0x394] = "10"
|
||||
g7t[95] = "11"
|
||||
g7t[0x3A6] = "12"
|
||||
g7t[0x393] = "13"
|
||||
g7t[0x39B] = "14"
|
||||
g7t[0x3A9] = "15"
|
||||
g7t[0x3A0] = "16"
|
||||
g7t[0x3A8] = "17"
|
||||
g7t[0x3A3] = "18"
|
||||
g7t[0x398] = "19"
|
||||
g7t[0x39E] = "1A"
|
||||
g7t[198] = "1C"
|
||||
g7t[230] = "1D"
|
||||
g7t[223] = "1E"
|
||||
g7t[201] = "1F"
|
||||
g7t[164] = "24"
|
||||
g7t[161] = "40"
|
||||
g7t[196] = "5B"
|
||||
g7t[214] = "5C"
|
||||
g7t[209] = "5D"
|
||||
g7t[220] = "5E"
|
||||
g7t[167] = "5F"
|
||||
g7t[191] = "60"
|
||||
g7t[228] = "7B"
|
||||
g7t[246] = "7C"
|
||||
g7t[241] = "7D"
|
||||
g7t[252] = "7E"
|
||||
g7t[224] = "7F"
|
||||
g7t[94] = "1B14"
|
||||
g7t[123] = "1B28"
|
||||
g7t[125] = "1B29"
|
||||
g7t[92] = "1B2F"
|
||||
g7t[91] = "1B3C"
|
||||
g7t[126] = "1B3D"
|
||||
g7t[93] = "1B3E"
|
||||
g7t[124] = "1B40"
|
||||
g7t[0x20AC] = "1B65"
|
||||
local unicode = ''
|
||||
local g7hex = ''
|
||||
local g7isok = true
|
||||
local j = #txt
|
||||
local res = nil
|
||||
local msg = nil
|
||||
local dcs = ""
|
||||
local k = 1
|
||||
repeat
|
||||
ch = string.byte(txt, k, k)
|
||||
if ch >= 0xF0 then
|
||||
ch = bitleft(bitand(ch, 7), 18)
|
||||
ch = bitor(bitleft(bitand(string.byte(txt, k + 1, k + 1), 0x3F), 12), ch)
|
||||
ch = bitor(bitleft(bitand(string.byte(txt, k + 2, k + 2), 0x3F), 6), ch)
|
||||
ch = bitor(bitand(string.byte(txt, k + 3, k + 3), 0x3F), ch) - 0x10000
|
||||
local w1 = bitor(0xD800, bitright(bitand(ch, 0xFFC00), 10))
|
||||
local w2 = bitor(0xDC00, bitand(ch, 0x3FF))
|
||||
unicode = unicode .. string.format("%04X", w1) .. string.format("%04X", w2)
|
||||
g7isok = false
|
||||
k = k + 3
|
||||
elseif ch >= 0xE0 then
|
||||
ch = bitleft(bitand(ch, 0xF), 12)
|
||||
ch = bitor(bitleft(bitand(string.byte(txt, k + 1, k + 1), 0x3F), 6), ch)
|
||||
ch = bitor(bitand(string.byte(txt, k + 2, k + 2), 0x3F), ch)
|
||||
res = g7t[ch]
|
||||
if res == nil then
|
||||
g7isok = false
|
||||
else
|
||||
g7hex = g7hex .. res
|
||||
end
|
||||
unicode = unicode .. string.format("%04X", ch)
|
||||
k = k + 2
|
||||
elseif ch >= 0xC0 then
|
||||
ch = bitleft(bitand(ch, 0x3F), 6)
|
||||
ch = bitor(bitand(string.byte(txt, k + 1, k + 1), 0x3F), ch)
|
||||
res = g7t[ch]
|
||||
if res == nil then
|
||||
g7isok = false
|
||||
else
|
||||
g7hex = g7hex .. res
|
||||
end
|
||||
unicode = unicode .. string.format("%04X", ch)
|
||||
k = k + 1
|
||||
elseif ch == 0x60 then
|
||||
unicode = unicode .. '0060'
|
||||
g7isok = false
|
||||
elseif ch <= 0x7F then
|
||||
res = g7t[ch]
|
||||
if res == nil then
|
||||
g7hex = g7hex .. string.format("%02X", ch)
|
||||
else
|
||||
g7hex = g7hex .. res
|
||||
end
|
||||
unicode = unicode .. string.format("%04X", ch)
|
||||
else
|
||||
g7hex = g7hex .. '3F'
|
||||
unicode = unicode .. '003F'
|
||||
end
|
||||
k = k + 1
|
||||
until k > j
|
||||
if g7isok and #g7hex <= 320 then
|
||||
dcs = "00"
|
||||
txt = g7hex
|
||||
elseif g7isok then
|
||||
msg = 'Processed text length = ' .. math.floor(#g7hex / 2) .. ' 7-bit characters.\n'
|
||||
msg = msg .. 'Currently ROOter supports 160 maximum per message.'
|
||||
elseif #unicode <= 280 then
|
||||
dcs = "08"
|
||||
txt = unicode
|
||||
else
|
||||
msg = 'Processed text length = ' .. math.floor(#unicode / 4) .. ' 16-bit Unicode characters.\n'
|
||||
msg = msg .. 'Currently ROOter supports 70 maximum per message.'
|
||||
end
|
||||
utf8togsm["msg"] = msg
|
||||
utf8togsm["dcs"] = dcs
|
||||
utf8togsm["txt"] = txt
|
||||
end
|
||||
return utf8togsm
|
33
rooter/0basicsupport/luci-app-guestwifi/Makefile
Normal file
33
rooter/0basicsupport/luci-app-guestwifi/Makefile
Normal file
@ -0,0 +1,33 @@
|
||||
#Owned by DairyMan@Whirlpool
|
||||
#
|
||||
#Copyright GNU act.
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-guestwifi
|
||||
PKG_VERSION:=1.000
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/luci-app-guestwifi
|
||||
SECTION:=utils
|
||||
CATEGORY:=ROOter
|
||||
SUBMENU:=Basic Applications
|
||||
TITLE:=support for Guest Wifi
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/luci-app-guestwifi/description
|
||||
Helper scripts to enable Guest Wifi
|
||||
endef
|
||||
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/luci-app-guestwifi/install
|
||||
$(CP) ./files/* $(1)/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,luci-app-guestwifi))
|
@ -0,0 +1,4 @@
|
||||
|
||||
config guest 'guestw'
|
||||
option 5g '1'
|
||||
|
@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
log() {
|
||||
logger -t "Guest Wifi" "$@"
|
||||
}
|
||||
|
||||
do_radio24() {
|
||||
local config=$1
|
||||
local channel
|
||||
|
||||
config_get channel $1 channel
|
||||
if [ $channel -gt 15 ]; then
|
||||
uci set guestwifi.$NAME.radio5g="1"
|
||||
fi
|
||||
}
|
||||
|
||||
NAME=$1
|
||||
|
||||
uci set guestwifi.$NAME=guestwifi
|
||||
uci set guestwifi.$NAME.ssid="Guest"
|
||||
uci set guestwifi.$NAME.freq="0"
|
||||
uci set guestwifi.$NAME.enabled="0"
|
||||
uci set guestwifi.$NAME.encrypted=""
|
||||
uci set guestwifi.$NAME.password=""
|
||||
uci set guestwifi.$NAME.qos="0"
|
||||
uci set guestwifi.$NAME.ul=""
|
||||
uci set guestwifi.$NAME.dl=""
|
||||
uci set guestwifi.$NAME.radio5g="0"
|
||||
config_load wireless
|
||||
config_foreach do_radio24 wifi-device
|
||||
uci commit guestwifi
|
@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
log() {
|
||||
logger -t "Guest Wifi" "$@"
|
||||
}
|
||||
|
||||
NAME=$1
|
@ -0,0 +1,200 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
log() {
|
||||
logger -t "Guest Wifi" "$@"
|
||||
}
|
||||
|
||||
do_radio() {
|
||||
local config=$1
|
||||
local freq=$2
|
||||
local channel
|
||||
|
||||
config_get channel $1 channel
|
||||
if [ $freq = "0" ]; then
|
||||
if [ $channel -lt 15 ]; then
|
||||
RADIO=$config
|
||||
fi
|
||||
else
|
||||
if [ $channel -gt 15 ]; then
|
||||
RADIO=$config
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
do_check() {
|
||||
local config=$1
|
||||
local wfreq=$2
|
||||
local enabled
|
||||
local freq
|
||||
|
||||
config_get enabled $1 enabled
|
||||
if [ $enabled = "1" ]; then
|
||||
config_get freq $1 freq
|
||||
if [ $freq = $wfreq ]; then
|
||||
CHECK=1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
NAME=$1
|
||||
RAD=$(uci -q get guestwifi.$NAME.freq)
|
||||
CHECK=0
|
||||
config_load guestwifi
|
||||
config_foreach do_check guestwifi $RAD
|
||||
if [ $CHECK -eq 1 ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
config_load wireless
|
||||
config_foreach do_radio wifi-device $RAD
|
||||
GUEST="guest""$RADIO"
|
||||
|
||||
LANIP=$(uci -q get network.lan.ipaddr)
|
||||
L1=$(echo $LANIP | cut -d. -f1)
|
||||
L2=$(echo $LANIP | cut -d. -f2)
|
||||
L3=$(echo $LANIP | cut -d. -f3)
|
||||
L4=$(echo $LANIP | cut -d. -f4)
|
||||
NL3="254"
|
||||
if [ $RAD = "0" ]; then
|
||||
NL3="253"
|
||||
fi
|
||||
if [ $L3 = "254" ]; then
|
||||
NL3="1"
|
||||
fi
|
||||
if [ $L3 = "253" ]; then
|
||||
NL3="2"
|
||||
fi
|
||||
IP="$L1"."$L2"."$NL3"."$L4"
|
||||
|
||||
ifname1="ifname"
|
||||
if [ -e /etc/newstyle ]; then
|
||||
ifname1="device"
|
||||
fi
|
||||
|
||||
WW=$(uci get -q network.$GUEST)
|
||||
if [ -z $WW ]; then
|
||||
# Configure guest network
|
||||
uci delete network.${GUEST}_dev
|
||||
uci set network.${GUEST}_dev=device
|
||||
uci set network.${GUEST}_dev.type=bridge
|
||||
uci set network.${GUEST}_dev.name="br-"$GUEST
|
||||
|
||||
uci delete network.$GUEST
|
||||
uci set network.$GUEST=interface
|
||||
uci set network.$GUEST.proto=static
|
||||
uci set network.$GUEST.ipaddr=$IP
|
||||
uci set network.$GUEST.$ifname1=br-${GUEST}
|
||||
uci set network.$GUEST.netmask=255.255.255.0
|
||||
|
||||
# Configure DHCP for guest network
|
||||
uci delete dhcp.$GUEST
|
||||
uci set dhcp.$GUEST=dhcp
|
||||
uci set dhcp.$GUEST.interface=$GUEST
|
||||
uci set dhcp.$GUEST.start=50
|
||||
uci set dhcp.$GUEST.limit=200
|
||||
uci set dhcp.$GUEST.leasetime=1h
|
||||
|
||||
# Configure firewall for guest network
|
||||
## Configure guest zone
|
||||
uci delete firewall.$GUEST"_zone"
|
||||
uci set firewall.$GUEST"_zone"=zone
|
||||
uci set firewall.$GUEST"_zone".name=$GUEST
|
||||
uci set firewall.$GUEST"_zone".network=$GUEST
|
||||
uci set firewall.$GUEST"_zone".input=REJECT
|
||||
uci set firewall.$GUEST"_zone".forward=REJECT
|
||||
uci set firewall.$GUEST"_zone".output=ACCEPT
|
||||
## Allow Guest -> Internet
|
||||
uci delete firewall.$GUEST"_forwarding"
|
||||
uci set firewall.$GUEST"_forwarding"=forwarding
|
||||
uci set firewall.$GUEST"_forwarding".src=$GUEST
|
||||
uci set firewall.$GUEST"_forwarding".dest=wan
|
||||
## Allow DNS Guest -> Router
|
||||
uci delete firewall.$GUEST"_rule_dns"
|
||||
uci set firewall.$GUEST"_rule_dns"=rule
|
||||
uci set firewall.$GUEST"_rule_dns".name="Allow "$GUEST" DNS Queries"
|
||||
uci set firewall.$GUEST"_rule_dns".src=$GUEST
|
||||
uci set firewall.$GUEST"_rule_dns".dest_port=53
|
||||
uci set firewall.$GUEST"_rule_dns".proto=tcpudp
|
||||
uci set firewall.$GUEST"_rule_dns".target=ACCEPT
|
||||
## Allow DHCP Guest -> Router
|
||||
uci delete firewall.$GUEST"_rule_dhcp"
|
||||
uci set firewall.$GUEST"_rule_dhcp"=rule
|
||||
uci set firewall.$GUEST"_rule_dhcp".name="Allow "$GUEST" DHCP request"
|
||||
uci set firewall.$GUEST"_rule_dhcp".src=$GUEST
|
||||
uci set firewall.$GUEST"_rule_dhcp".src_port=68
|
||||
uci set firewall.$GUEST"_rule_dhcp".dest_port=67
|
||||
uci set firewall.$GUEST"_rule_dhcp".proto=udp
|
||||
uci set firewall.$GUEST"_rule_dhcp".target=ACCEPT
|
||||
|
||||
uci commit
|
||||
fi
|
||||
|
||||
# Configure guest Wi-Fi
|
||||
SSID=$(uci -q get guestwifi.$NAME.ssid)
|
||||
ENCR=$(uci -q get guestwifi.$NAME.encrypted)
|
||||
|
||||
uci delete wireless.$NAME
|
||||
uci set wireless.$NAME=wifi-iface
|
||||
uci set wireless.$NAME.device=$RADIO
|
||||
uci set wireless.$NAME.mode=ap
|
||||
uci set wireless.$NAME.network=$GUEST
|
||||
uci set wireless.$NAME.ssid=$SSID
|
||||
case $ENCR in
|
||||
"0" )
|
||||
uci set wireless.$NAME.encryption="none"
|
||||
uci set wireless.$NAME.key=""
|
||||
;;
|
||||
"1" )
|
||||
uci set wireless.$NAME.encryption="psk"
|
||||
uci set wireless.$NAME.key=$(uci get guestwifi.$NAME.password)
|
||||
;;
|
||||
"2" )
|
||||
uci set wireless.$NAME.encryption="psk2"
|
||||
uci set wireless.$NAME.key=$(uci get guestwifi.$NAME.password)
|
||||
;;
|
||||
esac
|
||||
uci commit wireless
|
||||
|
||||
QOS=$(uci -q get guestwifi.$NAME.qos)
|
||||
|
||||
if [ $QOS = "1" ]; then
|
||||
DL=$(uci -q get guestwifi.$NAME.dl)
|
||||
let "DL=$DL * 1000"
|
||||
UL=$(uci -q get guestwifi.$NAME.ul)
|
||||
let "UL=$UL * 1000"
|
||||
IFACE="$(iwinfo | grep "ESSID" | grep $SSID)"
|
||||
WI=${IFACE% *}
|
||||
WI=${WI% *}
|
||||
uci delete sqm.$NAME
|
||||
uci set sqm.$NAME=queue
|
||||
uci set sqm.$NAME.interface=$WI
|
||||
uci set sqm.$NAME.enabled='1'
|
||||
uci set sqm.$NAME.upload=$DL
|
||||
uci set sqm.$NAME.download=$UL
|
||||
uci set sqm.$NAME.qdisc='cake'
|
||||
uci set sqm.$NAME.script='piece_of_cake.qos'
|
||||
uci set sqm.$NAME.qdisc_advanced='1'
|
||||
uci set sqm.$NAME.linklayer='none'
|
||||
uci set sqm.$NAME.ingress_ecn='ECN'
|
||||
uci set sqm.$NAME.egress_ecn='ECN'
|
||||
uci set sqm.$NAME.debug_logging='0'
|
||||
uci set sqm.$NAME.verbosity='5'
|
||||
uci set sqm.$NAME.squash_dscp='1'
|
||||
uci set sqm.$NAME.squash_ingress ='1'
|
||||
uci commit sqm
|
||||
/etc/init.d/sqm start
|
||||
/etc/init.d/sqm enable
|
||||
fi
|
||||
|
||||
|
||||
if [ -z $WW ]; then
|
||||
/etc/init.d/dnsmasq restart
|
||||
/etc/init.d/firewall restart
|
||||
/etc/init.d/network restart
|
||||
fi
|
||||
|
||||
|
||||
|
||||
uci set guestwifi.$NAME.enabled="1"
|
||||
uci commit guestwifi
|
@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
|
||||
log() {
|
||||
logger -t "Guest Wifi" "$@"
|
||||
}
|
||||
|
||||
NAME=$1
|
||||
|
||||
uci delete wireless.$NAME
|
||||
uci commit wireless
|
||||
QOS=$(uci get guestwifi.$NAME.qos)
|
||||
if [ $QOS = "1" ]; then
|
||||
uci delete sqm.$NAME
|
||||
uci commit sqm
|
||||
/etc/init.d/sqm start
|
||||
/etc/init.d/sqm enable
|
||||
fi
|
||||
uci set guestwifi.$NAME.enabled="0"
|
||||
uci commit guestwifi
|
@ -0,0 +1,22 @@
|
||||
module("luci.controller.guestwifi", package.seeall)
|
||||
|
||||
I18N = require "luci.i18n"
|
||||
translate = I18N.translate
|
||||
|
||||
function index()
|
||||
local page
|
||||
if not nixio.fs.access("/etc/config/wireless") then
|
||||
return
|
||||
end
|
||||
|
||||
page = entry({"admin", "network", "guestwifi"}, cbi("guestwifi", {hidesavebtn=true, hideresetbtn=true}), translate("Guest Wifi"), 22)
|
||||
page.dependent = true
|
||||
entry( {"admin", "network", "guestwifi", "edit"}, cbi("guestwifi-edit"), nil ).leaf = true
|
||||
|
||||
entry({"admin", "network", "createwifi"}, call("action_createwifi"))
|
||||
end
|
||||
|
||||
function action_createwifi()
|
||||
local set = luci.http.formvalue("set")
|
||||
os.execute("/usr/lib/guestwifi/create.sh " .. set)
|
||||
end
|
@ -0,0 +1,72 @@
|
||||
require("luci.ip")
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local multilock = uci:get("custom", "multiuser", "multi") or "0"
|
||||
local rootlock = uci:get("custom", "multiuser", "root") or "0"
|
||||
|
||||
local m = Map("guestwifi", translate("Guest Wifi Configuration"), translate("Set up a Guest Wifi"))
|
||||
|
||||
e = m:section(NamedSection, "guest", "")
|
||||
|
||||
m.on_init = function(self)
|
||||
--luci.sys.call("/usr/lib/wireguard/keygen.sh " .. arg[1])
|
||||
end
|
||||
|
||||
btn = e:option(Button, "_btn", translate(" "))
|
||||
btn.inputtitle = translate("Back to Main Page")
|
||||
btn.inputstyle = "apply"
|
||||
btn.redirect = luci.dispatcher.build_url(
|
||||
"admin", "network", "guestwifi"
|
||||
)
|
||||
function btn.write(self, section, value)
|
||||
luci.http.redirect( self.redirect )
|
||||
end
|
||||
|
||||
local s = m:section( NamedSection, arg[1], "guestwifi", translate("Instance Name : " .. arg[1]) )
|
||||
|
||||
ssid = s:option(Value, "ssid", translate("SSID :"));
|
||||
ssid.rmempty = true;
|
||||
ssid.optional=false;
|
||||
ssid.default="Guest";
|
||||
|
||||
bl = s:option(ListValue, "freq", translate("Frequency :"));
|
||||
bl:value("0", "2.4Ghz")
|
||||
bl.rmempty = true;
|
||||
bl.optional=false;
|
||||
wifi5g = uci:get("guestwifi", arg[1], "radio5g")
|
||||
if wifi5g == "1" then
|
||||
bl:value("1", "5.0Ghz")
|
||||
end
|
||||
|
||||
el = s:option(ListValue, "encrypted", translate("Encryption :"));
|
||||
el:value("0", translate("None"))
|
||||
el:value("1", translate("WPA-PSK (Medium Security)"))
|
||||
el:value("2", translate("WPA2-PSK (Strong Security)"))
|
||||
el.default=0
|
||||
|
||||
pass = s:option(Value, "password", translate("Password :"));
|
||||
pass.rmempty = true;
|
||||
pass.optional=false;
|
||||
pass.default="";
|
||||
pass.datatype="wpakey";
|
||||
pass.password = true
|
||||
|
||||
if (multilock == "0") then
|
||||
ql = s:option(ListValue, "qos", translate("Bandwidth Limited :"));
|
||||
ql:value("0", "Disabled")
|
||||
ql:value("1", "Enabled")
|
||||
ql.default=0
|
||||
|
||||
dl = s:option(Value, "dl", translate("Download Speed (Mbit/s) :"));
|
||||
dl.optional=false;
|
||||
dl.rmempty = true;
|
||||
dl.datatype = "and(uinteger,min(1))"
|
||||
dl.default=10
|
||||
|
||||
ul = s:option(Value, "ul", translate("Upload Speed (Mbit/s) :"));
|
||||
ul.optional=false;
|
||||
ul.rmempty = true;
|
||||
ul.datatype = "and(uinteger,min(1))"
|
||||
ul.default=2
|
||||
end
|
||||
|
||||
return m
|
@ -0,0 +1,128 @@
|
||||
local fs = require "nixio.fs"
|
||||
local sys = require "luci.sys"
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local testfullps = sys.exec("ps --help 2>&1 | grep BusyBox") --check which ps do we have
|
||||
local psstring = (string.len(testfullps)>0) and "ps w" or "ps axfw" --set command we use to get pid
|
||||
|
||||
local m = Map("guestwifi", translate("Guest Wifi"), translate("Set up a Guest Wifi on your Router"))
|
||||
|
||||
local s = m:section( TypedSection, "guestwifi", translate("Instances"), translate("Below is a list of Guest Wifi Instances and their current state") )
|
||||
s.template = "cbi/tblsection"
|
||||
s.template_addremove = "guestwifi/cbi-select-input-add"
|
||||
s.addremove = true
|
||||
s.add_select_options = { }
|
||||
|
||||
s.extedit = luci.dispatcher.build_url("admin", "network", "guestwifi", "edit", "%s")
|
||||
|
||||
function s.parse(self, section)
|
||||
local recipe = luci.http.formvalue(
|
||||
luci.cbi.CREATE_PREFIX .. self.config .. "." ..
|
||||
self.sectiontype .. ".select"
|
||||
)
|
||||
|
||||
if recipe and not s.add_select_options[recipe] then
|
||||
self.invalid_cts = true
|
||||
else
|
||||
TypedSection.parse( self, section )
|
||||
end
|
||||
end
|
||||
|
||||
function s.create(self, name)
|
||||
local recipe = luci.http.formvalue(
|
||||
luci.cbi.CREATE_PREFIX .. self.config .. "." ..
|
||||
self.sectiontype .. ".select"
|
||||
)
|
||||
local name = luci.http.formvalue(
|
||||
luci.cbi.CREATE_PREFIX .. self.config .. "." ..
|
||||
self.sectiontype .. ".text"
|
||||
)
|
||||
return 0
|
||||
end
|
||||
|
||||
function s.remove(self, name)
|
||||
sys.call("/usr/lib/guestwifi/stop.sh %s" % name)
|
||||
uci:delete("guestwifi", name)
|
||||
uci:save("guestwifi")
|
||||
uci:commit("guestwifi")
|
||||
end
|
||||
|
||||
|
||||
|
||||
local updown = s:option( Button, "_updown", translate("Start/Stop") )
|
||||
updown._state = false
|
||||
updown.redirect = luci.dispatcher.build_url(
|
||||
"admin", "network", "guestwifi"
|
||||
)
|
||||
function updown.cbid(self, section)
|
||||
local file_cfg = self.map:get(section, "enabled")
|
||||
if file_cfg == "1" then
|
||||
pid = 1
|
||||
else
|
||||
pid = nil
|
||||
end
|
||||
self._state = pid ~= nil
|
||||
self.option = self._state and "stop" or "start"
|
||||
return AbstractValue.cbid(self, section)
|
||||
end
|
||||
function updown.cfgvalue(self, section)
|
||||
self.title = self._state and "stop" or "start"
|
||||
self.inputstyle = self._state and "reset" or "reload"
|
||||
end
|
||||
function updown.write(self, section, value)
|
||||
if self.option == "stop" then
|
||||
sys.call("/usr/lib/guestwifi/stop.sh %s" % section)
|
||||
else
|
||||
sys.call("/usr/lib/guestwifi/start.sh %s" % section)
|
||||
end
|
||||
luci.http.redirect( self.redirect )
|
||||
end
|
||||
|
||||
local port = s:option( DummyValue, "ssid", translate("SSID") )
|
||||
|
||||
local freq = s:option( DummyValue, "freq", translate("Frequency") )
|
||||
function freq.cfgvalue(self, section)
|
||||
local val = AbstractValue.cfgvalue(self, section)
|
||||
if val == nil then
|
||||
val = "0"
|
||||
end
|
||||
if val == "1" then
|
||||
return "5.0Ghz"
|
||||
else
|
||||
return "2.4Ghz"
|
||||
end
|
||||
end
|
||||
|
||||
local auto = s:option( DummyValue, "encrypted", translate("Encryption") )
|
||||
function auto.cfgvalue(self, section)
|
||||
local val = AbstractValue.cfgvalue(self, section)
|
||||
if val == nil then
|
||||
val = 0
|
||||
end
|
||||
if val == "1" then
|
||||
return translate("WPA-PSK (Medium Security)")
|
||||
else
|
||||
if val == "2" then
|
||||
return translate("WPA2-PSK (Strong Security)")
|
||||
else
|
||||
return translate("None")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local qos = s:option( DummyValue, "qos", translate("Bandwidth Limiting") )
|
||||
function qos.cfgvalue(self, section)
|
||||
local val = AbstractValue.cfgvalue(self, section)
|
||||
if val == nil then
|
||||
val = 0
|
||||
end
|
||||
if val == "1" then
|
||||
dl_cfg = self.map:get(section, "dl")
|
||||
ul_cfg = self.map:get(section, "ul")
|
||||
return translate("Download : ") .. dl_cfg .. translate(" Mbit/s / Upload : ") .. ul_cfg .. translate(" Mbit/s")
|
||||
else
|
||||
return translate("Disabled")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return m
|
@ -0,0 +1,60 @@
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/xhr.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
function vpn_add()
|
||||
{
|
||||
var vpn_name = document.getElementById("instance_name1").value.replace(/[^\x00-\x7F]|[\s\.!@#$%^&*()\-+=\[\]{};':"\\|,<>\/?]/g,'');
|
||||
|
||||
if (!vpn_name || !vpn_name.length)
|
||||
{
|
||||
return info_message(vpn_output, "<%=pcdata(translate("The 'Name' field must not be empty!"))%>", 2000);
|
||||
}
|
||||
|
||||
document.getElementById("instance_name1").value = vpn_name;
|
||||
if (document.getElementById("cbi-guestwifi-" + vpn_name) != null)
|
||||
{
|
||||
return info_message(vpn_output, "<%=pcdata(translate("Instance with that name already exists!"))%>", 2000);
|
||||
}
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "network", "createwifi")%>',
|
||||
{ set: vpn_name },
|
||||
function(x, rv)
|
||||
{
|
||||
window.location.reload(false);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function info_message(output, msg, timeout)
|
||||
{
|
||||
timeout = timeout || 0;
|
||||
output.style.color = "red";
|
||||
output.innerHTML = '<em>' + msg + '</em>';
|
||||
if (timeout > 0)
|
||||
{
|
||||
setTimeout(function(){ output.innerHTML=""}, timeout);
|
||||
}
|
||||
}
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
<%+guestwifi/ovpn_css%>
|
||||
|
||||
<fieldset class="cbi-section" id="cbi-family">
|
||||
<div class="cbi-section-node">
|
||||
<div class="table cbi-section-table">
|
||||
<table width="700" border="0" id="tab12">
|
||||
<tr>
|
||||
<td> </td>
|
||||
</tr>
|
||||
</table>
|
||||
<h4><%:New Guest Wifi%></h4>
|
||||
<table width="700" border="0">
|
||||
<tr>
|
||||
<td width="10%"><input type="text" maxlength="20" placeholder="Instance name" id="instance_name1" /></td>
|
||||
<td width="10%"><input class="cbi-button cbi-button-add" type="submit" onclick="vpn_add(); return false;" value="<%:Add%>" title="<%:Add new Guest Wifi%>" /></td>
|
||||
<td width="80%"><span id="vpn_output"></span></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
@ -0,0 +1,38 @@
|
||||
<style type="text/css">
|
||||
h4
|
||||
{
|
||||
white-space: nowrap;
|
||||
border-bottom: 0px;
|
||||
margin: 10px 5px 5px 5px;
|
||||
}
|
||||
.tr
|
||||
{
|
||||
border: 0px;
|
||||
text-align: left;
|
||||
}
|
||||
.vpn-output
|
||||
{
|
||||
box-shadow: none;
|
||||
margin: 10px 5px 5px 5px;
|
||||
color: #a22;
|
||||
}
|
||||
textarea
|
||||
{
|
||||
border: 1px solid #cccccc;
|
||||
padding: 5px;
|
||||
font-size: 12px;
|
||||
font-family: monospace;
|
||||
resize: none;
|
||||
white-space: pre;
|
||||
overflow-wrap: normal;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
a
|
||||
{
|
||||
line-height: 1.5;
|
||||
}
|
||||
hr
|
||||
{
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
</style>
|
65
rooter/0drivers/rmbim/.svn/entries
Normal file
65
rooter/0drivers/rmbim/.svn/entries
Normal file
@ -0,0 +1,65 @@
|
||||
10
|
||||
|
||||
dir
|
||||
42347
|
||||
svn://svn.openwrt.org/openwrt/trunk/package/network/utils/umbim
|
||||
svn://svn.openwrt.org/openwrt
|
||||
|
||||
|
||||
|
||||
2014-08-26T09:36:59.015400Z
|
||||
42299
|
||||
blogic
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
3c298f89-4303-0410-b956-a3cf2f4a3e73
|
||||
|
||||
files
|
||||
dir
|
||||
|
||||
Makefile
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2014-08-31T18:28:32.000000Z
|
||||
47329758b279f0cfd6073b11ec66d486
|
||||
2014-08-26T09:36:59.015400Z
|
||||
42299
|
||||
blogic
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1141
|
||||
|
45
rooter/0drivers/rmbim/.svn/text-base/Makefile.svn-base
Normal file
45
rooter/0drivers/rmbim/.svn/text-base/Makefile.svn-base
Normal file
@ -0,0 +1,45 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=umbim
|
||||
PKG_VERSION:=2014-08-26
|
||||
PKG_RELEASE=$(PKG_SOURCE_VERSION)
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=git://git.openwrt.org/project/umbim.git
|
||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
|
||||
PKG_SOURCE_VERSION:=7741d88cdfd36f0c4380f660a9ad7109df76b432
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
|
||||
PKG_MAINTAINER:=John Crispin <blogic@openwrt.org>
|
||||
|
||||
PKG_LICENSE:=GPLv2
|
||||
PKG_LICENSE_FILES:=
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
define Package/umbim
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
DEPENDS:=+libubox +kmod-usb-net +kmod-usb-net-cdc-mbim
|
||||
TITLE:=Control utility for mobile broadband modems
|
||||
endef
|
||||
|
||||
define Package/umbim/description
|
||||
umbim is a command line tool for controlling mobile broadband modems using
|
||||
the MBIM-protocol.
|
||||
endef
|
||||
|
||||
TARGET_CFLAGS += \
|
||||
-I$(STAGING_DIR)/usr/include -ffunction-sections -fdata-sections
|
||||
|
||||
TARGET_LDFLAGS += -Wl,--gc-sections
|
||||
|
||||
define Package/umbim/install
|
||||
$(INSTALL_DIR) $(1)/sbin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/umbim $(1)/sbin/
|
||||
$(CP) ./files/* $(1)/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,umbim))
|
45
rooter/0drivers/rmbim/Makefile
Normal file
45
rooter/0drivers/rmbim/Makefile
Normal file
@ -0,0 +1,45 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=umbim
|
||||
PKG_RELEASE:=$(AUTORELEASE)
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/umbim.git
|
||||
PKG_SOURCE_DATE:=2021-08-18
|
||||
PKG_SOURCE_VERSION:=de5623104baee6e0c13c92f05c15bf4b4145c0b1
|
||||
PKG_MIRROR_HASH:=2d4a75d2b53c8413521a2fd138895e327bff3f4b4d29a540342b2d2e1e009852
|
||||
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
|
||||
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
PKG_LICENSE_FILES:=
|
||||
|
||||
PKG_FLAGS:=nonshared
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
define Package/rmbim
|
||||
SECTION:=net
|
||||
CATEGORY:=ROOter
|
||||
SUBMENU:=Drivers
|
||||
DEPENDS:=+libubox +kmod-usb-net +kmod-usb-net-cdc-mbim +luci-proto-mbim
|
||||
TITLE:=Control utility for mobile broadband modems
|
||||
endef
|
||||
|
||||
define Package/rmbim/description
|
||||
rmbim is a command line tool for controlling mobile broadband modems using
|
||||
the MBIM-protocol.
|
||||
endef
|
||||
|
||||
TARGET_CFLAGS += \
|
||||
-I$(STAGING_DIR)/usr/include -ffunction-sections -fdata-sections
|
||||
|
||||
TARGET_LDFLAGS += -Wl,--gc-sections
|
||||
|
||||
define Package/rmbim/install
|
||||
$(INSTALL_DIR) $(1)/sbin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/umbim $(1)/sbin/
|
||||
$(CP) ./files/* $(1)/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,rmbim))
|
612
rooter/0drivers/rmbim/files/lib/netifd/proto/mbim.sh
Normal file
612
rooter/0drivers/rmbim/files/lib/netifd/proto/mbim.sh
Normal file
@ -0,0 +1,612 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ -n "$INCLUDE_ONLY" ] || {
|
||||
. /lib/functions.sh
|
||||
. ../netifd-proto.sh
|
||||
init_proto "$@"
|
||||
}
|
||||
# DBG=-v
|
||||
|
||||
ROOTER=/usr/lib/rooter
|
||||
ROOTER_LINK="/tmp/links"
|
||||
|
||||
log() {
|
||||
modlog "MBIM Connect $CURRMODEM" "$@"
|
||||
}
|
||||
|
||||
enb=$(uci -q get custom.connect.ipv6)
|
||||
if [ -z $enb ]; then
|
||||
enb="1"
|
||||
fi
|
||||
|
||||
ifname1="ifname"
|
||||
if [ -e /etc/newstyle ]; then
|
||||
ifname1="device"
|
||||
fi
|
||||
|
||||
get_connect() {
|
||||
NAPN=$(uci -q get modem.modeminfo$CURRMODEM.apn)
|
||||
NAPN2=$(uci -q get modem.modeminfo$CURRMODEM.apn2)
|
||||
NUSER=$(uci -q get modem.modeminfo$CURRMODEM.user)
|
||||
NPASS=$(uci -q get modem.modeminfo$CURRMODEM.passw)
|
||||
NAUTH=$(uci -q get modem.modeminfo$CURRMODEM.auth)
|
||||
PINC=$(uci -q get modem.modeminfo$CURRMODEM.pincode)
|
||||
PDPT=$(uci -q get modem.modeminfo$CURRMODEM.pdptype)
|
||||
isplist=$(uci -q get modem.modeminfo$CURRMODEM.isplist)
|
||||
|
||||
apn=$NAPN
|
||||
apn2=$NAPN2
|
||||
username="$NUSER"
|
||||
password="$NPASS"
|
||||
auth=$NAUTH
|
||||
pincode=$PINC
|
||||
|
||||
if [ "$PDPT" = 0 ]; then
|
||||
ipt=""
|
||||
else
|
||||
IPVAR=$(uci -q get modem.modem$CURRMODEM.pdptype)
|
||||
case "$IPVAR" in
|
||||
"IP" )
|
||||
ipt="ipv4:"
|
||||
;;
|
||||
"IPV6" )
|
||||
ipt="ipv6:"
|
||||
;;
|
||||
"IPV4V6" )
|
||||
ipt="ipv4v6:"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
get_sub() {
|
||||
log "Checking subscriber"
|
||||
tid=$((tid + 1))
|
||||
SUB=$(umbim $DBG -n -t $tid -d $device subscriber)
|
||||
retq=$?
|
||||
if [ $retq -ne 0 ]; then
|
||||
log "Subscriber init failed"
|
||||
proto_notify_error "$interface" NO_SUBSCRIBER
|
||||
return 1
|
||||
fi
|
||||
CNUM=$(echo "$SUB" | awk '/number:/ {print $2}')
|
||||
IMSI=$(echo "$SUB" | awk '/subscriberid:/ {print $2}')
|
||||
uci set modem.modem$CURRMODEM.imsi=$IMSI
|
||||
ICCID=$(echo "$SUB" | awk '/simiccid:/ {print $2}')
|
||||
uci set modem.modem$CURRMODEM.iccid=$ICCID
|
||||
uci commit modem
|
||||
}
|
||||
|
||||
proto_mbim_init_config() {
|
||||
available=1
|
||||
no_device=1
|
||||
proto_config_add_string "device:device"
|
||||
proto_config_add_string apn
|
||||
proto_config_add_string apn2
|
||||
proto_config_add_string pincode
|
||||
proto_config_add_string delay
|
||||
proto_config_add_string auth
|
||||
proto_config_add_string username
|
||||
proto_config_add_string password
|
||||
}
|
||||
|
||||
_proto_mbim_setup() {
|
||||
local interface="$1"
|
||||
local tid=2
|
||||
local ret v6cap pdns v4dns v6dns
|
||||
|
||||
if [ ! -f /tmp/bootend.file ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
CURRMODEM=$(uci -q get network.$interface.currmodem)
|
||||
uci set modem.modem$CURRMODEM.connected=0
|
||||
uci commit modem
|
||||
rm -f $ROOTER_LINK/reconnect$CURRMODEM
|
||||
jkillall getsignal$CURRMODEM
|
||||
rm -f $ROOTER_LINK/getsignal$CURRMODEM
|
||||
jkillall con_monitor$CURRMODEM
|
||||
rm -f $ROOTER_LINK/con_monitor$CURRMODEM
|
||||
jkillall mbim_monitor$CURRMODEM
|
||||
rm -f $ROOTER_LINK/mbim_monitor$CURRMODEM
|
||||
|
||||
local device apn pincode delay
|
||||
json_get_vars device apn apn2 pincode delay auth username password
|
||||
|
||||
case $auth in
|
||||
"0" )
|
||||
auth=
|
||||
;;
|
||||
"1" )
|
||||
auth="pap"
|
||||
;;
|
||||
"2" )
|
||||
auth="chap"
|
||||
;;
|
||||
"*" )
|
||||
auth=
|
||||
;;
|
||||
esac
|
||||
|
||||
IMEI="Unknown"
|
||||
IMSI="Unknown"
|
||||
ICCID="Unknown"
|
||||
CNUM="*"
|
||||
CNUMx="*"
|
||||
|
||||
[ -n "$ctl_device" ] && device=$ctl_device
|
||||
|
||||
[ -n "$device" ] || {
|
||||
log "No control device specified"
|
||||
proto_notify_error "$interface" NO_DEVICE
|
||||
proto_set_available "$interface" 0
|
||||
return 1
|
||||
}
|
||||
[ -c "$device" ] || {
|
||||
log "The specified control device does not exist"
|
||||
proto_notify_error "$interface" NO_DEVICE
|
||||
proto_set_available "$interface" 0
|
||||
return 1
|
||||
}
|
||||
|
||||
devname="$(basename "$device")"
|
||||
devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)"
|
||||
ifname="$( ls "$devpath"/net )"
|
||||
|
||||
[ -n "$ifname" ] || {
|
||||
log "Failed to find matching interface"
|
||||
proto_notify_error "$interface" NO_IFNAME
|
||||
proto_set_available "$interface" 0
|
||||
return 1
|
||||
}
|
||||
|
||||
[ -n "$delay" ] && sleep "$delay"
|
||||
|
||||
log "Query radio state"
|
||||
umbim $DBG -n -d $device radio | grep "off"
|
||||
STATUS=$?
|
||||
|
||||
[ "$STATUS" -ne 0 ] || {
|
||||
sleep 1
|
||||
log "Setting FCC Auth"
|
||||
uqmi $DBG -s -m -d $device --fcc-auth
|
||||
sleep 1
|
||||
}
|
||||
|
||||
log "Reading capabilities"
|
||||
tid=$((tid + 1))
|
||||
DCAPS=$(umbim $DBG -n -t $tid -d $device caps)
|
||||
retq=$?
|
||||
if [ $retq -ne 0 ]; then
|
||||
|
||||
log "Failed to read modem caps"
|
||||
tid=$((tid + 1))
|
||||
umbim $DBG -t $tid -d "$device" disconnect
|
||||
proto_notify_error "$interface" PIN_FAILED
|
||||
return 1
|
||||
fi
|
||||
CUSTOM=$(echo "$DCAPS" | awk '/customdataclass:/ {print $2}')
|
||||
IMEI=$(echo "$DCAPS" | awk '/deviceid:/ {print $2}')
|
||||
uci set modem.modem$CURRMODEM.imei=$IMEI
|
||||
echo 'CUSTOM="'"$CUSTOM"'"' > /tmp/mbimcustom$CURRMODEM
|
||||
|
||||
get_sub
|
||||
|
||||
if [ ! -f /tmp/profile$CURRMODEM ]; then
|
||||
$ROOTER/connect/get_profile.sh $CURRMODEM
|
||||
fi
|
||||
|
||||
get_connect
|
||||
|
||||
log "Checking PIN state"
|
||||
tid=$((tid + 1))
|
||||
umbim $DBG -n -t $tid -d $device pinstate
|
||||
retq=$?
|
||||
if [ $retq -eq 2 ]; then
|
||||
log "PIN is required"
|
||||
if [ ! -z $pincode ]; then
|
||||
log "Sending PIN"
|
||||
tid=$((tid + 1))
|
||||
umbim $DBG -n -t $tid -d $device unlock "$pincode" 2>/dev/null
|
||||
retq=$?
|
||||
if [ $retq -ne 0 ]; then
|
||||
log "PIN unlock failed"
|
||||
exit 1
|
||||
else
|
||||
log "PIN unlocked"
|
||||
sleep 3
|
||||
CHKPORT=$(uci get modem.modem$CURRMODEM.commport)
|
||||
if [ ! -z $CHKPORT ]; then
|
||||
$ROOTER/common/gettype.sh $CURRMODEM
|
||||
else
|
||||
get_sub
|
||||
fi
|
||||
fi
|
||||
else
|
||||
log "PIN is missing in the profile"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
log "PIN is not required"
|
||||
fi
|
||||
|
||||
log "Register with network"
|
||||
for i in $(seq 30); do
|
||||
tid=$((tid + 1))
|
||||
REG=$(umbim $DBG -n -t $tid -d $device registration)
|
||||
retq=$?
|
||||
[ $retq -ne 2 ] && break
|
||||
sleep 2
|
||||
done
|
||||
if [ $retq != 0 ]; then
|
||||
if [ $retq != 4 ]; then
|
||||
log "Subscriber registration failed"
|
||||
proto_notify_error "$interface" NO_REGISTRATION
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
MCCMNC=$(echo "$REG" | awk '/provider_id:/ {print $2}')
|
||||
PROV=$(echo "$REG" | awk '/provider_name:/ {print $2}')
|
||||
MCC=${MCCMNC:0:3}
|
||||
MNC=${MCCMNC:3}
|
||||
|
||||
tid=$((tid + 1))
|
||||
|
||||
log "Attach to network"
|
||||
ATTACH=$(umbim $DBG -n -t $tid -d $device attach)
|
||||
retq=$?
|
||||
if [ $retq != 0 ]; then
|
||||
log "Failed to attach to network"
|
||||
proto_notify_error "$interface" ATTACH_FAILED
|
||||
return 1
|
||||
fi
|
||||
UP=$(echo "$ATTACH" | awk '/uplinkspeed:/ {print $2}')
|
||||
DOWN=$(echo "$ATTACH" | awk '/downlinkspeed:/ {print $2}')
|
||||
|
||||
tid=$((tid + 1))
|
||||
|
||||
for isp in $isplist
|
||||
do
|
||||
NAPN=$(echo $isp | cut -d, -f2)
|
||||
NPASS=$(echo $isp | cut -d, -f4)
|
||||
CID=$(echo $isp | cut -d, -f5)
|
||||
NUSER=$(echo $isp | cut -d, -f6)
|
||||
NAUTH=$(echo $isp | cut -d, -f7)
|
||||
if [ "$NPASS" = "nil" ]; then
|
||||
NPASS="NIL"
|
||||
fi
|
||||
if [ "$NUSER" = "nil" ]; then
|
||||
NUSER="NIL"
|
||||
fi
|
||||
if [ "$NAUTH" = "nil" ]; then
|
||||
NAUTH="0"
|
||||
fi
|
||||
apn=$NAPN
|
||||
username="$NUSER"
|
||||
password="$NPASS"
|
||||
auth=$NAUTH
|
||||
case $auth in
|
||||
"0" )
|
||||
auth="none"
|
||||
;;
|
||||
"1" )
|
||||
auth="pap"
|
||||
;;
|
||||
"2" )
|
||||
auth="chap"
|
||||
;;
|
||||
"*" )
|
||||
auth="none"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ ! -e /etc/config/isp ]; then
|
||||
log "Connect to network using $apn"
|
||||
else
|
||||
log "Connect to network"
|
||||
fi
|
||||
|
||||
if [ ! -e /etc/config/isp ]; then
|
||||
log "$ipt $apn $auth $username $password"
|
||||
fi
|
||||
|
||||
tidd=0
|
||||
tcnt=4
|
||||
while ! umbim $DBG -n -t $tid -d $device connect "$ipt""$apn" "$auth" "$username" "$password"; do
|
||||
tid=$((tid + 1))
|
||||
sleep 1;
|
||||
tidd=$((tidd + 1))
|
||||
if [ $tidd -gt $tcnt ]; then
|
||||
break;
|
||||
fi
|
||||
done
|
||||
if [ $tidd -le $tcnt ]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ $tidd -gt $tcnt ]; then
|
||||
log "Failed to connect to network"
|
||||
return 1
|
||||
fi
|
||||
|
||||
tid=$((tid + 1))
|
||||
|
||||
log "Get IP config"
|
||||
CONFIG=$(umbim $DBG -n -t $tid -d $device config) || {
|
||||
log "config failed"
|
||||
return 1
|
||||
}
|
||||
|
||||
IP=$(echo -e "$CONFIG"|grep "ipv4address"|grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")
|
||||
GATE=$(echo -e "$CONFIG"|grep "ipv4gateway"|grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")
|
||||
DNS1=$(echo -e "$CONFIG"|grep "ipv4dnsserver"|grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" |sed -n 1p)
|
||||
DNS2=$(echo -e "$CONFIG"|grep "ipv4dnsserver"|grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" |sed -n 2p)
|
||||
if [ $enb = "1" ]; then
|
||||
IP6=$(echo "$CONFIG" | awk '/ipv6address:/ {print $2}' | cut -d / -f 1)
|
||||
DNS3=$(echo "$CONFIG" | awk '/ipv6dnsserver:/ {print $2}' | sed -n 1p)
|
||||
DNS4=$(echo "$CONFIG" | awk '/ipv6dnsserver:/ {print $2}' | sed -n 2p)
|
||||
fi
|
||||
echo "$GATE" > /tmp/mbimgateway
|
||||
|
||||
[ -n "$IP" ] && echo "IP: $IP"
|
||||
[ -n "$DNS1" ] && echo "DNS1: $DNS1"
|
||||
[ -n "$DNS2" ] && echo "DNS2: $DNS2"
|
||||
if [ $enb = "1" ]; then
|
||||
[ -n "$IP6" ] && echo "IPv6: $IP6"
|
||||
[ -n "$DNS3" ] && echo "DNS3: $DNS3"
|
||||
[ -n "$DNS4" ] && echo "DNS4: $DNS4"
|
||||
fi
|
||||
|
||||
log "Connected, setting IP"
|
||||
|
||||
if [ $enb = "1" ]; then
|
||||
if [ -n "$IP6" -a -z "$IP" ]; then
|
||||
log "Running IPv6-only mode"
|
||||
nat46=1
|
||||
fi
|
||||
|
||||
if [[ $(echo "$IP6" | grep -o "^[23]") ]]; then
|
||||
# Global unicast IP acquired
|
||||
v6cap=1
|
||||
elif
|
||||
[[ $(echo "$IP6" | grep -o "^[0-9a-fA-F]\{1,4\}:") ]]; then
|
||||
# non-routable address
|
||||
v6cap=2
|
||||
else
|
||||
v6cap=0
|
||||
fi
|
||||
fi
|
||||
|
||||
INTER=$(uci get modem.modem$CURRMODEM.inter)
|
||||
if [ -e /tmp/v4dns$INTER -o -e /tmp/v6dns$INTER ]; then
|
||||
pdns=1
|
||||
if [ -e /tmp/v4dns$INTER ]; then
|
||||
v4dns=$(cat /tmp/v4dns$INTER 2>/dev/null)
|
||||
fi
|
||||
if [ $enb = "1" ]; then
|
||||
if [ -e /tmp/v6dns$INTER ]; then
|
||||
v6dns=$(cat /tmp/v6dns$INTER 2>/dev/null)
|
||||
fi
|
||||
fi
|
||||
else
|
||||
v4dns="$DNS1 $DNS2"
|
||||
if [ $enb = "1" ]; then
|
||||
v6dns="$DNS3 $DNS4"
|
||||
fi
|
||||
fi
|
||||
|
||||
proto_init_update "$ifname" 1
|
||||
|
||||
if [ -n "$IP" ]; then
|
||||
proto_add_ipv4_address $IP "255.255.255.255"
|
||||
proto_add_ipv4_route "0.0.0.0" 0
|
||||
fi
|
||||
|
||||
for DNSV in $(echo "$v4dns"); do
|
||||
proto_add_dns_server "$DNSV"
|
||||
done
|
||||
|
||||
if [ $enb = "1" ]; then
|
||||
if [ "$v6cap" -gt 0 ]; then
|
||||
# RFC 7278: Extend an IPv6 /64 Prefix to LAN
|
||||
proto_add_ipv6_address $IP6 128
|
||||
if [ "$v6cap" = 1 ]; then
|
||||
proto_add_ipv6_prefix $IP6/64
|
||||
proto_add_ipv6_route "::0" 0 "" "" "" $IP6/64
|
||||
for DNSV in $(echo "$v6dns"); do
|
||||
proto_add_dns_server "$DNSV"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
proto_add_data
|
||||
json_add_string zone wan
|
||||
proto_close_data
|
||||
|
||||
proto_send_update "$interface"
|
||||
|
||||
if [ $enb = "1" ]; then
|
||||
if [ "$v6cap" -gt 0 ]; then
|
||||
local zone="$(fw3 -q network "$interface" 2>/dev/null)"
|
||||
fi
|
||||
if [ "$v6cap" = 2 ]; then
|
||||
log "Adding IPv6 dynamic interface"
|
||||
json_init
|
||||
json_add_string name "${interface}_6"
|
||||
json_add_string ${ifname1} "@$interface"
|
||||
json_add_string proto "dhcpv6"
|
||||
json_add_string extendprefix 1
|
||||
[ -n "$zone" ] && json_add_string zone "$zone"
|
||||
[ "$nat46" = 1 ] || json_add_string iface_464xlat 0
|
||||
json_add_boolean peerdns 0
|
||||
json_add_array dns
|
||||
for DNSV in $(echo "$v6dns"); do
|
||||
json_add_string "" "$DNSV"
|
||||
done
|
||||
json_close_array
|
||||
proto_add_dynamic_defaults
|
||||
json_close_object
|
||||
ubus call network add_dynamic "$(json_dump)"
|
||||
elif
|
||||
[ "$v6cap" = 1 -a "$nat46" = 1 ]; then
|
||||
log "Adding 464XLAT (CLAT) dynamic interface"
|
||||
json_init
|
||||
json_add_string name "CLAT$INTER"
|
||||
json_add_string proto "464xlat"
|
||||
json_add_string tunlink "${interface}"
|
||||
[ -n "$zone" ] && json_add_string zone "$zone"
|
||||
proto_add_dynamic_defaults
|
||||
json_close_object
|
||||
ubus call network add_dynamic "$(json_dump)"
|
||||
fi
|
||||
fi
|
||||
|
||||
tid=$((tid + 1))
|
||||
uci_set_state network $interface tid "$tid"
|
||||
# SIGNAL=$(umbim $DBG -n -t $tid -d $device signal)
|
||||
# CSQ=$(echo "$SIGNAL" | awk '/rssi:/ {print $2}')
|
||||
|
||||
$ROOTER/log/logger "Modem #$CURRMODEM Connected"
|
||||
log "Modem $CURRMODEM Connected"
|
||||
|
||||
IDP=$(uci get modem.modem$CURRMODEM.idP)
|
||||
IDV=$(uci get modem.modem$CURRMODEM.idV)
|
||||
|
||||
if [ ! -s /tmp/msimdata$CURRMODEM ]; then
|
||||
echo $IDV" : "$IDP > /tmp/msimdatax$CURRMODEM
|
||||
echo "$IMEI" >> /tmp/msimdatax$CURRMODEM
|
||||
echo "$IMSI" >> /tmp/msimdatax$CURRMODEM
|
||||
echo "$ICCID" >> /tmp/msimdatax$CURRMODEM
|
||||
echo "1" >> /tmp/msimdatax$CURRMODEM
|
||||
mv -f /tmp/msimdatax$CURRMODEM /tmp/msimdata$CURRMODEM
|
||||
fi
|
||||
|
||||
if [ ! -s /tmp/msimnum$CURRMODEM ]; then
|
||||
echo "$CNUM" > /tmp/msimnumx$CURRMODEM
|
||||
echo "$CNUMx" >> /tmp/msimnumx$CURRMODEM
|
||||
mv -f /tmp/msimnumx$CURRMODEM /tmp/msimnum$CURRMODEM
|
||||
fi
|
||||
|
||||
uci set modem.modem$CURRMODEM.custom=$CUSTOM
|
||||
uci set modem.modem$CURRMODEM.provider=$PROV
|
||||
uci set modem.modem$CURRMODEM.down=$DOWN" kbps Down | "
|
||||
uci set modem.modem$CURRMODEM.up=$UP" kbps Up"
|
||||
uci set modem.modem$CURRMODEM.mcc=$MCC
|
||||
uci set modem.modem$CURRMODEM.mnc=" "$MNC
|
||||
uci set modem.modem$CURRMODEM.sig="--"
|
||||
uci set modem.modem$CURRMODEM.sms=0
|
||||
uci commit modem
|
||||
|
||||
COMMPORT=$(uci get modem.modem$CURRMODEM.commport)
|
||||
if [ -z $COMMPORT ]; then
|
||||
ln -s $ROOTER/mbim/mbimdata.sh $ROOTER_LINK/getsignal$CURRMODEM
|
||||
else
|
||||
$ROOTER/sms/check_sms.sh $CURRMODEM &
|
||||
ln -s $ROOTER/signal/modemsignal.sh $ROOTER_LINK/getsignal$CURRMODEM
|
||||
# send custom AT startup command
|
||||
if [ $(uci -q get modem.modeminfo$CURRMODEM.at) -eq "1" ]; then
|
||||
ATCMDD=$(uci -q get modem.modeminfo$CURRMODEM.atc)
|
||||
if [ ! -z "${ATCMDD}" ]; then
|
||||
OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
OX=$($ROOTER/common/processat.sh "$OX")
|
||||
ERROR="ERROR"
|
||||
if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1`
|
||||
then
|
||||
log "Error sending custom AT command: $ATCMDD with result: $OX"
|
||||
else
|
||||
log "Sent custom AT command: $ATCMDD with result: $OX"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
ln -s $ROOTER/connect/reconnect.sh $ROOTER_LINK/reconnect$CURRMODEM
|
||||
$ROOTER_LINK/getsignal$CURRMODEM $CURRMODEM $PROT &
|
||||
ln -s $ROOTER/connect/conmon.sh $ROOTER_LINK/con_monitor$CURRMODEM
|
||||
$ROOTER_LINK/con_monitor$CURRMODEM $CURRMODEM &
|
||||
#ln -s $ROOTER/mbim/monitor.sh $ROOTER_LINK/mbim_monitor$CURRMODEM
|
||||
#$ROOTER_LINK/mbim_monitor$CURRMODEM $CURRMODEM $device &
|
||||
|
||||
uci set modem.modem$CURRMODEM.connected=1
|
||||
uci commit modem
|
||||
|
||||
if [ -e $ROOTER/connect/postconnect.sh ]; then
|
||||
$ROOTER/connect/postconnect.sh $CURRMODEM
|
||||
fi
|
||||
|
||||
if [ -e $ROOTER/timezone.sh ]; then
|
||||
TZ=$(uci -q get modem.modeminfo$CURRMODEM.tzone)
|
||||
if [ "$TZ" = "1" ]; then
|
||||
$ROOTER/timezone.sh &
|
||||
fi
|
||||
fi
|
||||
CLB=$(uci -q get modem.modeminfo$CURRMODEM.lb)
|
||||
if [ -e /etc/config/mwan3 ]; then
|
||||
INTER=$(uci get modem.modeminfo$CURRMODEM.inter)
|
||||
if [ -z $INTER ]; then
|
||||
INTER=0
|
||||
else
|
||||
if [ $INTER = 0 ]; then
|
||||
INTER=$CURRMODEM
|
||||
fi
|
||||
fi
|
||||
ENB=$(uci -q get mwan3.wan$CURRMODEM.enabled)
|
||||
if [ ! -z $ENB ]; then
|
||||
if [ $CLB = "1" ]; then
|
||||
uci set mwan3.wan$INTER.enabled=1
|
||||
else
|
||||
uci set mwan3.wan$INTER.enabled=0
|
||||
fi
|
||||
uci commit mwan3
|
||||
/usr/sbin/mwan3 restart
|
||||
fi
|
||||
fi
|
||||
rm -f /tmp/usbwait
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
proto_mbim_setup() {
|
||||
|
||||
local ret
|
||||
_proto_mbim_setup $@
|
||||
ret=$?
|
||||
|
||||
[ "$ret" = 0 ] || {
|
||||
log "MBIM bringup failed, retry in 5s"
|
||||
CPORT=$(uci get modem.modem$CURRMODEM.commport)
|
||||
ATCMDD="AT+COPS=0"
|
||||
OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
sleep 5
|
||||
}
|
||||
|
||||
exit 0
|
||||
return $ret
|
||||
}
|
||||
|
||||
proto_mbim_teardown() {
|
||||
local interface="$1"
|
||||
|
||||
local device
|
||||
json_get_vars device
|
||||
local tid=$(uci_get_state network $interface tid)
|
||||
|
||||
[ -n "$ctl_device" ] && device=$ctl_device
|
||||
|
||||
if [ -n "$device" ]; then
|
||||
log "Stopping network"
|
||||
if [ -n "$tid" ]; then
|
||||
tid=$((tid + 1))
|
||||
umbim $DBG -t $tid -d "$device" disconnect
|
||||
uci_revert_state network $interface tid
|
||||
else
|
||||
umbim $DBG -d "$device" disconnect
|
||||
fi
|
||||
fi
|
||||
|
||||
proto_init_update "*" 0
|
||||
proto_send_update "$interface"
|
||||
|
||||
}
|
||||
|
||||
[ -n "$INCLUDE_ONLY" ] || add_protocol mbim
|
115
rooter/0drivers/rmbim/files/usr/lib/rooter/mbim/mbimdata.sh
Normal file
115
rooter/0drivers/rmbim/files/usr/lib/rooter/mbim/mbimdata.sh
Normal file
@ -0,0 +1,115 @@
|
||||
#!/bin/sh
|
||||
|
||||
ROOTER=/usr/lib/rooter
|
||||
ROOTER_LINK=$ROOTER"/links"
|
||||
|
||||
log() {
|
||||
logger -t "MBIM Data" "$@"
|
||||
}
|
||||
|
||||
STARTIMEX=$(date +%s)
|
||||
MONSTAT=
|
||||
rm -f /tmp/monstat$CURRMODEM
|
||||
|
||||
build_status() {
|
||||
CSQ=$signal
|
||||
if [ $CSQ -ge 0 -a $CSQ -le 31 ]; then
|
||||
CSQ_PER=$(($CSQ * 100/31))
|
||||
CSQ_RSSI=$((2 * CSQ - 113))
|
||||
CSQX=$CSQ_RSSI
|
||||
[ $CSQ -eq 0 ] && CSQ_RSSI="<= "$CSQ_RSSI
|
||||
[ $CSQ -eq 31 ] && CSQ_RSSI=">= "$CSQ_RSSI
|
||||
CSQ_PER=$CSQ_PER"%"
|
||||
CSQ_RSSI=$CSQ_RSSI" dBm"
|
||||
else
|
||||
CSQ="-"
|
||||
CSQ_PER="-"
|
||||
CSQ_RSSI="-"
|
||||
fi
|
||||
echo "-" > /tmp/status$CURRMODEM.file
|
||||
echo "$CSQ" >> /tmp/status$CURRMODEM.file
|
||||
echo "$CSQ_PER" >> /tmp/status$CURRMODEM.file
|
||||
echo "$CSQ_RSSI" >> /tmp/status$CURRMODEM.file
|
||||
echo "$manuf" >> /tmp/status$CURRMODEM.file
|
||||
echo "$provider" >> /tmp/status$CURRMODEM.file
|
||||
echo "$cellmode" >> /tmp/status$CURRMODEM.file
|
||||
echo "-" >> /tmp/status$CURRMODEM.file
|
||||
echo "-" >> /tmp/status$CURRMODEM.file
|
||||
echo "-" >> /tmp/status$CURRMODEM.file
|
||||
echo "-" >> /tmp/status$CURRMODEM.file
|
||||
echo "$mcc" >> /tmp/status$CURRMODEM.file
|
||||
echo "$mnc" >> /tmp/status$CURRMODEM.file
|
||||
echo "-" >> /tmp/status$CURRMODEM.file
|
||||
echo "-" >> /tmp/status$CURRMODEM.file
|
||||
echo "$down" >> /tmp/status$CURRMODEM.file
|
||||
echo "$up" >> /tmp/status$CURRMODEM.file
|
||||
echo "-" >> /tmp/status$CURRMODEM.file
|
||||
echo "-" >> /tmp/status$CURRMODEM.file
|
||||
echo " " >> /tmp/status$CURRMODEM.file
|
||||
echo " " >> /tmp/status$CURRMODEM.file
|
||||
echo "$MONSTAT" >> /tmp/status$CURRMODEM.file
|
||||
echo "-" >> /tmp/status$CURRMODEM.file
|
||||
echo "-" >> /tmp/status$CURRMODEM.file
|
||||
echo "$conn" >> /tmp/status$CURRMODEM.file
|
||||
echo "-" >> /tmp/status$CURRMODEM.file
|
||||
echo "-" >> /tmp/status$CURRMODEM.file
|
||||
echo "-" >> /tmp/status$CURRMODEM.file
|
||||
echo "-" >> /tmp/status$CURRMODEM.file
|
||||
echo "-" >> /tmp/status$CURRMODEM.file
|
||||
echo "MBIM" >> /tmp/status$CURRMODEM.file
|
||||
echo "-" >> /tmp/status$CURRMODEM.file
|
||||
echo "-" >> /tmp/status$CURRMODEM.file
|
||||
echo "-" >> /tmp/status$CURRMODEM.file
|
||||
}
|
||||
|
||||
CURRMODEM=$1
|
||||
|
||||
conn="Modem #"$CURRMODEM
|
||||
custom=$(uci get modem.modem$CURRMODEM.custom)
|
||||
port=$(uci get modem.modem$CURRMODEM.wdm)
|
||||
netd=$(uci get modem.modem$CURRMODEM.wwan)
|
||||
manuf=$(uci get modem.modem$CURRMODEM.manuf)
|
||||
model=$(uci get modem.modem$CURRMODEM.model)
|
||||
mcc=$(uci get modem.modem$CURRMODEM.mcc)
|
||||
mnc=$(uci get modem.modem$CURRMODEM.mnc)
|
||||
up=$(uci get modem.modem$CURRMODEM.up)
|
||||
down=$(uci get modem.modem$CURRMODEM.down)
|
||||
provider=$(uci get modem.modem$CURRMODEM.provider)
|
||||
cellmode=$(uci get modem.modem$CURRMODEM.mode)
|
||||
if [ $cellmode = "CUSTOM" ]; then
|
||||
cellmode=$custom
|
||||
fi
|
||||
signal=$(uci get modem.modem$CURRMODEM.sig)
|
||||
|
||||
device="/dev/cdc-wdm"$port
|
||||
netdev="wwan"$netd
|
||||
manuf=$manuf" "$model
|
||||
|
||||
tid=2
|
||||
while [ 1 -eq 1 ]; do
|
||||
tid=2
|
||||
#SIGNAL=$(umbim -n -t $tid -d $device signal)
|
||||
tid=$((tid + 1))
|
||||
#SIGNAL=$(umbim -n -t $tid -d $device signal)
|
||||
signal=0
|
||||
if [ -e /tmp/monstat$CURRMODEM ]; then
|
||||
source /tmp/monstat$CURRMODEM
|
||||
fi
|
||||
if [ -z $MONSTAT ]; then
|
||||
MONSTAT="Unknown"
|
||||
fi
|
||||
build_status
|
||||
if [ -e /etc/netspeed ]; then
|
||||
NETSPEED=60
|
||||
else
|
||||
NETSPEED=10
|
||||
fi
|
||||
CURRTIME=$(date +%s)
|
||||
let ELAPSE=CURRTIME-STARTIMEX
|
||||
while [ $ELAPSE -lt $NETSPEED ]; do
|
||||
sleep 2
|
||||
CURRTIME=$(date +%s)
|
||||
let ELAPSE=CURRTIME-STARTIMEX
|
||||
done
|
||||
STARTIMEX=$CURRTIME
|
||||
done
|
45
rooter/0drivers/rmbim/files/usr/lib/rooter/mbim/monitor.sh
Normal file
45
rooter/0drivers/rmbim/files/usr/lib/rooter/mbim/monitor.sh
Normal file
@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /lib/functions.sh
|
||||
|
||||
ROOTER_LINK="/tmp/links"
|
||||
|
||||
log() {
|
||||
logger -t "MBIM Monitor" "$@"
|
||||
}
|
||||
|
||||
CURRMODEM=$1
|
||||
DEVICE=$2
|
||||
|
||||
while :; do
|
||||
tid=$(uci_get_state network wan$CURRMODEM tid)
|
||||
tid=$((tid + 1))
|
||||
umbim -d $DEVICE -n -t $tid status >/dev/null
|
||||
retq=$?
|
||||
uci_toggle_state network wan$CURRMODEM tid $tid
|
||||
[ $retq -ne 0 ] && break
|
||||
sleep 10
|
||||
done
|
||||
|
||||
case $retq in
|
||||
2)
|
||||
error="activation state: activating"
|
||||
;;
|
||||
3)
|
||||
error="activation state: deactivated"
|
||||
;;
|
||||
4)
|
||||
error="activation state: deactivating"
|
||||
;;
|
||||
255)
|
||||
error="MBIM message not long enough"
|
||||
;;
|
||||
esac
|
||||
|
||||
log "Modem $CURRMODEM Connection is Down ($error)"
|
||||
if [ -f $ROOTER_LINK/reconnect$CURRMODEM ]; then
|
||||
$ROOTER_LINK/reconnect$CURRMODEM $CURRMODEM &
|
||||
fi
|
||||
|
||||
# wait to be killed by mbim.sh
|
||||
sleep 60
|
52
rooter/0drivers/rqmi/Makefile
Normal file
52
rooter/0drivers/rqmi/Makefile
Normal file
@ -0,0 +1,52 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=uqmi
|
||||
PKG_RELEASE:=$(AUTORELEASE)
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/uqmi.git
|
||||
PKG_SOURCE_DATE:=2022-05-04
|
||||
PKG_SOURCE_VERSION:=56cb2d4056fef132ccf78dfb6f3074ae5d109992
|
||||
PKG_MIRROR_HASH:=cc832b5318805df8c8387a3650f250dee72d5f1dbda4e4866b5503e186b2210c
|
||||
PKG_MAINTAINER:=Matti Laakso <malaakso@elisanet.fi>
|
||||
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
PKG_LICENSE_FILES:=
|
||||
|
||||
PKG_FLAGS:=nonshared
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
define Package/rqmi
|
||||
SECTION:=net
|
||||
CATEGORY:=ROOter
|
||||
SUBMENU:=Drivers
|
||||
DEPENDS:=+libubox +libblobmsg-json +kmod-usb-net +kmod-usb-net-qmi-wwan +wwan
|
||||
TITLE:=Control utility for mobile broadband modems
|
||||
endef
|
||||
|
||||
define Package/rqmi/description
|
||||
uqmi is a command line tool for controlling mobile broadband modems using
|
||||
the QMI-protocol.
|
||||
endef
|
||||
|
||||
TARGET_CFLAGS += \
|
||||
-I$(STAGING_DIR)/usr/include \
|
||||
-ffunction-sections \
|
||||
-fdata-sections \
|
||||
-Wno-error=dangling-pointer \
|
||||
-Wno-error=maybe-uninitialized
|
||||
|
||||
TARGET_LDFLAGS += -Wl,--gc-sections
|
||||
|
||||
CMAKE_OPTIONS += \
|
||||
-DDEBUG=1
|
||||
|
||||
define Package/rqmi/install
|
||||
$(INSTALL_DIR) $(1)/sbin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/uqmi $(1)/sbin/
|
||||
$(CP) ./files/* $(1)/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,rqmi))
|
293
rooter/0drivers/rqmi/files/usr/lib/rooter/qmi/connectqmi.sh
Normal file
293
rooter/0drivers/rqmi/files/usr/lib/rooter/qmi/connectqmi.sh
Normal file
@ -0,0 +1,293 @@
|
||||
#!/bin/sh
|
||||
|
||||
ROOTER=/usr/lib/rooter
|
||||
|
||||
log() {
|
||||
modlog "QMI Connect $CURRMODEM" "$@"
|
||||
}
|
||||
|
||||
. /lib/functions.sh
|
||||
. /lib/netifd/netifd-proto.sh
|
||||
|
||||
CURRMODEM=$1
|
||||
devname=$2
|
||||
device=/dev/$2
|
||||
auth=$3
|
||||
NAPN=$4
|
||||
username=$5
|
||||
password=$6
|
||||
RAW=$7
|
||||
DHCP=$8
|
||||
pincode=$9
|
||||
|
||||
enb=$(uci -q get custom.connect.ipv6)
|
||||
if [ -z $enb ]; then
|
||||
enb="1"
|
||||
fi
|
||||
|
||||
ifname1="ifname"
|
||||
if [ -e /etc/newstyle ]; then
|
||||
ifname1="device"
|
||||
fi
|
||||
|
||||
INTER=$(uci -q get modem.modem$CURRMODEM.inter)
|
||||
interface="wan"$INTER
|
||||
|
||||
case $auth in
|
||||
"0" )
|
||||
auth="none"
|
||||
;;
|
||||
"1" )
|
||||
auth="pap"
|
||||
;;
|
||||
"2" )
|
||||
auth="chap"
|
||||
;;
|
||||
*)
|
||||
auth="none"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ $username = NIL ]; then
|
||||
username=
|
||||
fi
|
||||
if [ $password = NIL ]; then
|
||||
password=
|
||||
fi
|
||||
|
||||
ifname="$(ls /sys/class/usbmisc/$devname/device/net/)"
|
||||
|
||||
#while uqmi -s -d "$device" --get-pin-status | grep '"UIM uninitialized"' > /dev/null; do
|
||||
# sleep 1;
|
||||
#done
|
||||
|
||||
[ -n "$pincode" ] && {
|
||||
uqmi -s -d "$device" --verify-pin1 "$pincode" || {
|
||||
log "Unable to verify PIN"
|
||||
ret=1
|
||||
}
|
||||
}
|
||||
|
||||
uqmi -s -d "$device" --stop-network 0xffffffff --autoconnect > /dev/null & sleep 5 ; kill -9 $!
|
||||
uqmi -s -d "$device" --set-device-operating-mode online > /dev/null 2>&1 & sleep 5 ; kill -9 $!
|
||||
|
||||
if [ $RAW -eq 1 ]; then
|
||||
DATAFORM='"raw-ip"'
|
||||
else
|
||||
if [ $idV = 1199 -a $idP = 9055 ]; then
|
||||
$ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "reset.gcom" "$CURRMODEM"
|
||||
DATAFORM='"802.3"'
|
||||
uqmi -s -d "$device" --set-data-format 802.3
|
||||
uqmi -s -d "$device" --wda-set-data-format 802.3
|
||||
else
|
||||
log "getting data format"
|
||||
DATAFORM=$(uqmi -s -d "$device" --wda-get-data-format)
|
||||
fi
|
||||
fi
|
||||
|
||||
log "WDA-GET-DATA-FORMAT is $DATAFORM"
|
||||
if [ "$DATAFORM" = '"raw-ip"' ]; then
|
||||
[ -f /sys/class/net/$ifname/qmi/raw_ip ] || {
|
||||
log "Device only supports raw-ip mode but is missing this required driver attribute: /sys/class/net/$ifname/qmi/raw_ip"
|
||||
ret=1
|
||||
}
|
||||
echo "Y" > /sys/class/net/$ifname/qmi/raw_ip
|
||||
fi
|
||||
|
||||
log "Query radio state"
|
||||
uqmi -s -d "$device" --get-signal-info | grep -q "Information unavailable" & sleep 5 ; kill -9 $!
|
||||
STATUS=$?
|
||||
|
||||
[ "$STATUS" -ne 0 ] || {
|
||||
sleep 1
|
||||
log "Setting FCC Auth"
|
||||
uqmi -s -d "$device" --fcc-auth & sleep 5 ; kill -9 $!
|
||||
sleep 1
|
||||
}
|
||||
|
||||
uqmi -s -d "$device" --sync > /dev/null 2>&1 & sleep 5 ; kill -9 $!
|
||||
|
||||
#uqmi -s -d "$device" --network-register > /dev/null 2>&1
|
||||
|
||||
log "Waiting for network registration"
|
||||
td=0
|
||||
while uqmi -s -d "$device" --get-serving-system | grep '"searching"' > /dev/null; do
|
||||
sleep 5;
|
||||
tid=$((tid + 1))
|
||||
if [ $tid -gt 2 ]; then
|
||||
uqmi -s -d "$device" --stop-network 0xffffffff --autoconnect > /dev/null & sleep 10 ; kill -9 $!
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
cid=`uqmi -s -d "$device" --get-client-id wds`
|
||||
[ $? -ne 0 ] && {
|
||||
log "Unable to obtain client ID"
|
||||
ret=1
|
||||
}
|
||||
|
||||
uqmi -s -d "$device" --set-client-id wds,"$cid" --set-ip-family ipv4 > /dev/null
|
||||
|
||||
isplist=$(uci -q get modem.modeminfo$CURRMODEM.isplist)
|
||||
apn2=$(uci -q get modem.modeminfo$CURRMODEM.apn2)
|
||||
for isp in $isplist
|
||||
do
|
||||
NAPN=$(echo $isp | cut -d, -f2)
|
||||
NPASS=$(echo $isp | cut -d, -f4)
|
||||
CID=$(echo $isp | cut -d, -f5)
|
||||
NUSER=$(echo $isp | cut -d, -f6)
|
||||
NAUTH=$(echo $isp | cut -d, -f7)
|
||||
if [ "$NPASS" = "nil" ]; then
|
||||
NPASS="NIL"
|
||||
fi
|
||||
if [ "$NUSER" = "nil" ]; then
|
||||
NUSER="NIL"
|
||||
fi
|
||||
if [ "$NAUTH" = "nil" ]; then
|
||||
NAUTH="0"
|
||||
fi
|
||||
username="$NUSER"
|
||||
password="$NPASS"
|
||||
auth=$NAUTH
|
||||
case $auth in
|
||||
"0" )
|
||||
auth="none"
|
||||
;;
|
||||
"1" )
|
||||
auth="pap"
|
||||
;;
|
||||
"2" )
|
||||
auth="chap"
|
||||
;;
|
||||
"*" )
|
||||
auth="none"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ ! -e /etc/config/isp ]; then
|
||||
log "Connect to network using $NAPN"
|
||||
else
|
||||
log "Connect to network"
|
||||
fi
|
||||
|
||||
if [ ! -e /etc/config/isp ]; then
|
||||
log "$NAPN $auth $username $password"
|
||||
fi
|
||||
|
||||
conn=0
|
||||
tidd=0
|
||||
tcnt=4
|
||||
while true; do
|
||||
ST=$(uqmi -s -d "$device" --set-client-id wds,"$cid" --start-network ${NAPN:+--apn $NAPN} ${auth:+--auth-type $auth} \
|
||||
${username:+--username $username} ${password:+--password $password})
|
||||
log "Connection returned : $ST"
|
||||
CONN=$(uqmi -s -d "$device" --get-data-status)
|
||||
log "Status is $CONN"
|
||||
if [[ $(echo "$CONN" | grep -o "disconnected") ]]; then
|
||||
sleep 1
|
||||
tidd=$((tidd + 1))
|
||||
if [ $tidd -gt $tcnt ]; then
|
||||
break
|
||||
fi
|
||||
else
|
||||
conn=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ $conn -eq 1 ]; then
|
||||
break;
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -z $(echo "$CONN" | grep -o "disconnected") ]]; then
|
||||
ret=0
|
||||
|
||||
CONN4=$(uqmi -s -d "$device" --set-client-id wds,"$cid" --get-current-settings)
|
||||
log "GET-CURRENT-SETTINGS is $CONN4"
|
||||
|
||||
if [ $enb = "1" ]; then
|
||||
cid6=`uqmi -s -d "$device" --get-client-id wds`
|
||||
[ $? -ne 0 ] && {
|
||||
log "Unable to obtain client ID"
|
||||
ret=1
|
||||
}
|
||||
|
||||
uqmi -s -d "$device" --set-client-id wds,"$cid6" --set-ip-family ipv6 > /dev/null
|
||||
ST6=$(uqmi -s -d "$device" --set-client-id wds,"$cid6" --start-network ${NAPN:+--apn $NAPN} ${auth:+--auth-type $auth} \
|
||||
${username:+--username $username} ${password:+--password $password})
|
||||
log "IPv6 Connection returned : $ST6"
|
||||
CONN6=$(uqmi -s -d "$device" --set-client-id wds,"$cid6" --get-current-settings)
|
||||
CONF6=$(jsonfilter -s $CONN6 -e '@.ipv6')
|
||||
if [ -n "$CONF6" ];then
|
||||
log "IPv6 settings are $CONF6"
|
||||
touch /tmp/ipv6supp$INTER
|
||||
else
|
||||
rm -f /tmp/ipv6supp$INTER
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $DATAFORM = '"raw-ip"' ]; then
|
||||
log "Handle raw-ip"
|
||||
json_load "$CONN4"
|
||||
json_select ipv4
|
||||
json_get_vars ip subnet gateway dns1 dns2
|
||||
if [ $enb = "1" ]; then
|
||||
if [ -n "$CONF6" ]; then
|
||||
json_load "$CONN6"
|
||||
json_select ipv6
|
||||
json_get_var ip_6 ip
|
||||
json_get_var gateway_6 gateway
|
||||
json_get_var dns1_6 dns1
|
||||
json_get_var dns2_6 dns2
|
||||
json_get_var ip_prefix_length ip-prefix-length
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -s /tmp/v4dns$INTER -o -s /tmp/v6dns$INTER ]; then
|
||||
pdns=1
|
||||
if [ -s /tmp/v4dns$INTER ]; then
|
||||
v4dns=$(cat /tmp/v4dns$INTER 2>/dev/null)
|
||||
fi
|
||||
if [ $enb = "1" ]; then
|
||||
if [ -s /tmp/v6dns$INTER ]; then
|
||||
v6dns=$(cat /tmp/v6dns$INTER 2>/dev/null)
|
||||
fi
|
||||
fi
|
||||
else
|
||||
v4dns="$dns1 $dns2"
|
||||
if [ $enb = "1" ]; then
|
||||
v6dns="$dns1_6 $dns2_6"
|
||||
echo "$v6dns" > /tmp/v6dns$INTER
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $DHCP -eq 0 ]; then
|
||||
log Applying IP settings to wan$INTER
|
||||
uci delete network.wan$INTER
|
||||
uci set network.wan$INTER=interface
|
||||
uci set network.wan$INTER.proto=static
|
||||
uci set network.wan$INTER.${ifname1}=$ifname
|
||||
uci set network.wan$INTER.metric=$INTER"0"
|
||||
uci set network.wan$INTER.ipaddr=$ip/$subnet
|
||||
uci set network.wan$INTER.gateway='0.0.0.0'
|
||||
uci set network.wan$INTER.dns="$v4dns"
|
||||
uci commit network
|
||||
uci set modem.modem$CURRMODEM.interface=$ifname
|
||||
uci commit modem
|
||||
else
|
||||
proto_init_update "$ifname" 1
|
||||
proto_set_keep 1
|
||||
proto_add_ipv4_address "$ip" "$subnet"
|
||||
proto_add_ipv4_route "0.0.0.0" 0
|
||||
for DNSV in $(echo "$v4dns"); do
|
||||
proto_add_dns_server "$DNSV"
|
||||
done
|
||||
proto_send_update "$interface"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
uqmi -s -d "$device" --stop-network 0xffffffff --autoconnect > /dev/null & sleep 10 ; kill -9 $!
|
||||
ret=1
|
||||
fi
|
||||
|
||||
exit $ret
|
34
rooter/0mesh/mesh-mesh/Makefile
Normal file
34
rooter/0mesh/mesh-mesh/Makefile
Normal file
@ -0,0 +1,34 @@
|
||||
#Owned by DairyMan@Whirlpool
|
||||
#
|
||||
#Copyright GNU act.
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=mesh-mesh
|
||||
PKG_VERSION:=4.500
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/mesh-mesh
|
||||
SECTION:=utils
|
||||
CATEGORY:=ROOter
|
||||
SUBMENU:=Mesh Support
|
||||
DEPENDS:=+kmod-batman-adv +alfred +batctl +ip
|
||||
TITLE:=Install scripts for Mesh Network
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/mesh-mesh/description
|
||||
Install scripts for Mesh Network
|
||||
endef
|
||||
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/mesh-mesh/install
|
||||
$(CP) ./files/* $(1)/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,mesh-mesh))
|
16
rooter/0mesh/mesh-mesh/files/etc/config/batman-adv
Normal file
16
rooter/0mesh/mesh-mesh/files/etc/config/batman-adv
Normal file
@ -0,0 +1,16 @@
|
||||
config mesh 'bat0'
|
||||
option aggregated_ogms '1'
|
||||
option ap_isolation '0'
|
||||
option bonding '0'
|
||||
option fragmentation '0'
|
||||
option gw_bandwidth '10000/2000'
|
||||
option gw_mode 'client'
|
||||
option gw_sel_class '20'
|
||||
option log_level '2'
|
||||
option orig_interval '1000'
|
||||
option bridge_loop_avoidance '1'
|
||||
option distributed_arp_table '1'
|
||||
option multicast_mode '1'
|
||||
option network_coding '0'
|
||||
option hop_penalty '30'
|
||||
option isolation_mark '0'
|
18
rooter/0mesh/mesh-mesh/files/etc/config/mesh
Normal file
18
rooter/0mesh/mesh-mesh/files/etc/config/mesh
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
config radio 'radio'
|
||||
option radionumber '0'
|
||||
option usedfs '1'
|
||||
option channelwidth '0'
|
||||
option channellist '0'
|
||||
option channelindex '10'
|
||||
option dedicated '0'
|
||||
|
||||
config network 'network'
|
||||
option networkid 'MeshCloud'
|
||||
option netencrypted '1'
|
||||
option netpassword 'MeshPassword123'
|
||||
|
||||
config roam 'roam'
|
||||
option signalenable '1'
|
||||
option signalid 'abcd'
|
||||
|
34
rooter/0mesh/mesh-mesh/files/etc/hotplug.d/net/99-batman-gw
Normal file
34
rooter/0mesh/mesh-mesh/files/etc/hotplug.d/net/99-batman-gw
Normal file
@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
|
||||
dhcp4_discover () {
|
||||
ifup lan_dhcp
|
||||
}
|
||||
|
||||
dhcp4_kill () {
|
||||
ifdown lan_dhcp
|
||||
}
|
||||
|
||||
dnsmasq_start () {
|
||||
uci revert -P/var/state dhcp.@dnsmasq[0].domainneeded
|
||||
uci revert -P/var/state dhcp.@dnsmasq[0].boguspriv
|
||||
uci revert -P/var/state dhcp.@dnsmasq[0].rebind_protection
|
||||
uci revert -P/var/state dhcp.lan.ignore
|
||||
/etc/init.d/dnsmasq restart
|
||||
}
|
||||
|
||||
dnsmasq_stop () {
|
||||
uci set -P/var/state dhcp.@dnsmasq[0].domainneeded=
|
||||
uci set -P/var/state dhcp.@dnsmasq[0].boguspriv=
|
||||
uci set -P/var/state dhcp.@dnsmasq[0].rebind_protection=0
|
||||
uci set -P/var/state dhcp.lan.ignore=1
|
||||
echo no-dhcp-interface=br-lan >> /var/etc/dnsmasq.conf
|
||||
/etc/init.d/dnsmasq restart
|
||||
}
|
||||
|
||||
if [ "$BATTYPE" = "gw" ] ; then
|
||||
case "$BATACTION" in
|
||||
add) dnsmasq_stop ; dhcp4_discover ;;
|
||||
del) dhcp4_kill ; dnsmasq_start ;;
|
||||
change) dhcp4_kill ; sleep 5 ; dhcp4_discover ;;
|
||||
esac
|
||||
fi
|
9
rooter/0mesh/mesh-mesh/files/etc/init.d/zmesh
Normal file
9
rooter/0mesh/mesh-mesh/files/etc/init.d/zmesh
Normal file
@ -0,0 +1,9 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2006 OpenWrt.org
|
||||
|
||||
START=99
|
||||
|
||||
start() {
|
||||
/usr/lib/mesh/checker.sh
|
||||
}
|
||||
|
@ -0,0 +1,249 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2012 Jo-Philipp Wich <xm@subsignal.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
module("luci.controller.batman", package.seeall)
|
||||
|
||||
local function split(str, pat)
|
||||
local t = {} -- NOTE: use {n = 0} in Lua-5.0
|
||||
local fpat = "(.-)" .. pat
|
||||
local last_end = 1
|
||||
local s, e, cap = str:find(fpat, 1)
|
||||
while s do
|
||||
if s ~= 1 or cap ~= "" then
|
||||
table.insert(t,cap)
|
||||
end
|
||||
last_end = e+1
|
||||
s, e, cap = str:find(fpat, last_end)
|
||||
end
|
||||
if last_end <= #str then
|
||||
cap = str:sub(last_end)
|
||||
table.insert(t, cap)
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
|
||||
function index()
|
||||
local page
|
||||
|
||||
page = node("admin", "mesh", "batman")
|
||||
page.target = template("batman/batman")
|
||||
page.title = _("Mesh Status")
|
||||
page.order = 1
|
||||
|
||||
node("batman")
|
||||
|
||||
page = node("batman", "json")
|
||||
page.target = call("act_json")
|
||||
|
||||
page = node("batman", "topo")
|
||||
page.target = call("act_topo")
|
||||
page.leaf = true
|
||||
|
||||
page = node("batman", "graph")
|
||||
page.target = template("batman_graph")
|
||||
page.leaf = true
|
||||
end
|
||||
|
||||
function act_topo(mode)
|
||||
if not mode or mode == "dot" or mode == "json" then
|
||||
local fd = io.popen("batadv-vis -f %s" %( mode or "dot" ))
|
||||
if fd then
|
||||
if mode == "json" then
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write("[")
|
||||
local ln
|
||||
repeat
|
||||
ln = fd:read("*l")
|
||||
if ln then
|
||||
luci.http.write(ln)
|
||||
luci.http.write(", ")
|
||||
end
|
||||
until not ln
|
||||
luci.http.write("{ } ]")
|
||||
else
|
||||
luci.http.prepare_content("text/vnd.graphviz")
|
||||
luci.http.header("Content-Disposition",
|
||||
"attachment; filename=topo-%s-%s.vd"
|
||||
%{ luci.sys.hostname(), os.date("%Y%m%d-%H%M%S") })
|
||||
luci.http.write(fd:read("*a"))
|
||||
end
|
||||
fd:close()
|
||||
else
|
||||
luci.http.status(500, "No data")
|
||||
end
|
||||
else
|
||||
luci.http.status(500, "Bad mode")
|
||||
end
|
||||
end
|
||||
|
||||
function act_json()
|
||||
local v, l, fd
|
||||
local rv = {
|
||||
interfaces = { },
|
||||
originators = { },
|
||||
gateways = { }
|
||||
}
|
||||
|
||||
--
|
||||
-- interfaces
|
||||
--
|
||||
fd = io.popen("batctl if")
|
||||
if fd then
|
||||
repeat
|
||||
l = fd:read("*l")
|
||||
v = l and l:match("^(.-):")
|
||||
if v then
|
||||
rv.interfaces[#rv.interfaces+1] = v
|
||||
end
|
||||
until not l
|
||||
fd:close()
|
||||
end
|
||||
|
||||
os.execute("cat /proc/net/arp > /tmp/arp")
|
||||
|
||||
iplist = {}
|
||||
maclist = {}
|
||||
index = 0
|
||||
fd = io.open("/tmp/arp")
|
||||
if fd then
|
||||
-- skip header line
|
||||
fd:read("*l")
|
||||
repeat
|
||||
l = fd:read("*l")
|
||||
if l then
|
||||
lan = l
|
||||
s1, e1 = lan:find("0x2")
|
||||
if s1 ~= nil then
|
||||
s, e = l:find(" ")
|
||||
if s ~= nil then
|
||||
ip = l:sub(0, e-1)
|
||||
|
||||
fc = io.popen("batctl translate " .. ip)
|
||||
if fc then
|
||||
mac = fc:read("*l")
|
||||
fc:close()
|
||||
iplist[index] = ip
|
||||
maclist[index] = mac
|
||||
index = index + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
until not l
|
||||
fd:close()
|
||||
end
|
||||
|
||||
--
|
||||
-- originators
|
||||
--
|
||||
local originators_command = (
|
||||
"batctl o -H 2>/dev/null ".. -- gets originators from batctl
|
||||
"| tr -d '[]()' ".. -- removes brackets and parenthesis
|
||||
"| sed 's/^ / -/g' ".. -- normalizes output, adding a minus when no asterisk is outputed in each line
|
||||
"| sed 's/^ //g' ".. -- removes the space from the beginning of the line
|
||||
"| sed -r 's/\\s+/,/g'".. -- replaces tabs for commas
|
||||
"| sed -r 's/s,/,/g'" -- removes the 's' from the last_seen field referencing seconds
|
||||
)
|
||||
fd = io.popen(originators_command)
|
||||
if fd then
|
||||
repeat
|
||||
l = fd:read()
|
||||
if l then
|
||||
local asterisk, originator_name, last_seen, link_quality, next_hop, outgoing_if
|
||||
asterisk, originator_name, last_seen, link_quality, next_hop, outgoing_if = unpack(split(l, ","))
|
||||
if originator_name and last_seen and link_quality then
|
||||
if originator_name == next_hop then
|
||||
next_hop = "Here"
|
||||
end
|
||||
if index > 0 then
|
||||
for j=0,index-1 do
|
||||
if maclist[j] == originator_name then
|
||||
originator_name = iplist[j] .. " (" .. originator_name .. ")"
|
||||
end
|
||||
if maclist[j] == next_hop then
|
||||
next_hop = iplist[j]
|
||||
end
|
||||
end
|
||||
end
|
||||
rv.originators[#rv.originators+1] = {
|
||||
originator_name,
|
||||
tonumber(last_seen) * 1000,
|
||||
tonumber(link_quality),
|
||||
next_hop,
|
||||
outgoing_if
|
||||
}
|
||||
end
|
||||
end
|
||||
until not l
|
||||
fd:close()
|
||||
end
|
||||
|
||||
--
|
||||
-- gateways
|
||||
--
|
||||
fd = io.popen("batctl gwl")
|
||||
if fd then
|
||||
-- skip header line
|
||||
fd:read("*l")
|
||||
fd:read("*l")
|
||||
|
||||
repeat
|
||||
l = fd:read("*l")
|
||||
if l then
|
||||
local a, m, q, n, i, r = l:match("^(%S*) +([^ ]+) +%( *(%d+)%) +([^ ]+) +%[ *(%S+)%]: +(%S+)")
|
||||
if a and m and q and n and i and r then
|
||||
c="0"
|
||||
if index > 0 then
|
||||
for j=0,index-1 do
|
||||
if maclist[j] == m then
|
||||
m = iplist[j]
|
||||
end
|
||||
if maclist[j] == n then
|
||||
n = iplist[j]
|
||||
end
|
||||
end
|
||||
end
|
||||
rv.gateways[#rv.gateways+1] = {
|
||||
#a > 0,
|
||||
m,
|
||||
tonumber(q),
|
||||
n,
|
||||
i,
|
||||
tonumber(c),
|
||||
r
|
||||
}
|
||||
end
|
||||
end
|
||||
until not l
|
||||
fd:close()
|
||||
end
|
||||
|
||||
-- local Gateway status
|
||||
|
||||
rv.status = "Client"
|
||||
fd = io.popen("batctl gw")
|
||||
if fd then
|
||||
l = fd:read("*l")
|
||||
s, e = l:find("server")
|
||||
if s ~= nil then
|
||||
rv.status = "Server"
|
||||
end
|
||||
fd:close()
|
||||
end
|
||||
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
end
|
@ -0,0 +1,76 @@
|
||||
module("luci.controller.mesh", package.seeall)
|
||||
function index()
|
||||
local page
|
||||
entry({"admin", "mesh"}, firstchild(), "Mesh", 71).dependent=false
|
||||
page = entry({"admin", "mesh", "mesh"}, template("mesh/mesh-setup"), "Mesh Configuration", 71)
|
||||
page.dependent = true
|
||||
|
||||
entry({"admin", "mesh", "getstate"}, call("action_getstate"))
|
||||
entry({"admin", "mesh", "sendmeshstate"}, call("action_sendmeshstate"))
|
||||
entry({"admin", "mesh", "meshcfg"}, call("action_meshcfg"))
|
||||
entry({"admin", "mesh", "meshstartstop"}, call("action_meshstartstop"))
|
||||
end
|
||||
|
||||
function action_getstate()
|
||||
local rv = {}
|
||||
local radiolist = {}
|
||||
|
||||
file = io.open("/etc/meshrun", "r")
|
||||
if file == nil then
|
||||
rv["state"] = "0"
|
||||
else
|
||||
rv["state"] = "1"
|
||||
file:close()
|
||||
end
|
||||
os.execute("/usr/lib/mesh/radio.sh ")
|
||||
file = io.open("/tmp/radiolist", "r")
|
||||
if file ~= nil then
|
||||
j = file:read("*line")
|
||||
rv['radio'] = j
|
||||
if j ~=0 then
|
||||
for i=0, j-1 do
|
||||
radiolist[i] = file:read("*line")
|
||||
end
|
||||
rv['radiolist'] = radiolist
|
||||
end
|
||||
rv['radionumber'] = file:read("*line")
|
||||
rv['channelindex'] = file:read("*line")
|
||||
rv['channellist'] = file:read("*line")
|
||||
rv['channelwidth'] = file:read("*line")
|
||||
rv['usedfs'] = file:read("*line")
|
||||
rv['dedicated'] = file:read("*line")
|
||||
|
||||
rv['networkid'] = file:read("*line")
|
||||
rv['netencrypted'] = file:read("*line")
|
||||
rv['netpassword'] = file:read("*line")
|
||||
|
||||
rv['signalenable'] = file:read("*line")
|
||||
rv['signalid'] = file:read("*line")
|
||||
|
||||
file:close()
|
||||
else
|
||||
rv["radio"] = "0"
|
||||
end
|
||||
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
end
|
||||
|
||||
function action_sendmeshstate()
|
||||
local set = luci.http.formvalue("set")
|
||||
|
||||
os.execute('/usr/lib/mesh/save.sh "' .. set .. '"')
|
||||
end
|
||||
|
||||
function action_meshcfg()
|
||||
local set = luci.http.formvalue("set")
|
||||
|
||||
os.execute('/usr/lib/mesh/savecfg.sh "' .. set .. '"')
|
||||
end
|
||||
|
||||
function action_meshstartstop()
|
||||
os.execute('/usr/lib/mesh/startstop.sh')
|
||||
os.execute("reboot &")
|
||||
end
|
||||
|
@ -0,0 +1,300 @@
|
||||
<%#
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2012 Jo-Philipp Wich <xm@subsignal.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
|
||||
-%>
|
||||
|
||||
<% luci.http.prepare_content("text/html") %>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
|
||||
<script type="text/javascript" src="<%=resource%>/dracula/raphael-min.js"></script>
|
||||
<script type="text/javascript" src="<%=resource%>/dracula/dracula_graffle.js"></script>
|
||||
<script type="text/javascript" src="<%=resource%>/dracula/dracula_graph.js"></script>
|
||||
<script type="text/javascript" src="<%=resource%>/jquery/jquery-1.4.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
function gw_apply(field)
|
||||
{
|
||||
var mode, val;
|
||||
|
||||
if (field.type == 'radio') {
|
||||
val = '';
|
||||
mode = field.value;
|
||||
}
|
||||
else {
|
||||
val = field.value;
|
||||
mode = document.getElementById('gw_gateway').checked ? 'server' : 'client';
|
||||
}
|
||||
|
||||
document.getElementById('gw_apply').style.display = '';
|
||||
document.getElementById('gw_form').style.display = 'none';
|
||||
document.getElementById('gw_form_val').parentNode.style.display = (mode != 'off') ? '' : 'none';
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("batman/gw")%>/'+mode+'/'+encodeURIComponent(val), null,
|
||||
function(x, info) {
|
||||
document.getElementById('gw_form').style.display = '';
|
||||
document.getElementById('gw_apply').style.display = 'none';
|
||||
document.getElementById('gw_form_val').value = info;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
XHR.poll(5, '<%=luci.dispatcher.build_url("batman/json")%>', null,
|
||||
function(x, info)
|
||||
{
|
||||
var t;
|
||||
|
||||
var og = info.originators;
|
||||
var gw = info.gateways;
|
||||
var server = info.status;
|
||||
|
||||
if ( server == 'Client' )
|
||||
{
|
||||
document.getElementById('status').innerHTML="No local Internet access, running as Client";
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById('status').innerHTML="Local Internet access, running as Gateway Server";
|
||||
}
|
||||
|
||||
if (!!(t = document.getElementById('originator_table')))
|
||||
{
|
||||
/* clear all rows */
|
||||
while (t.rows.length > 1)
|
||||
t.rows[0].parentNode.deleteRow(1);
|
||||
|
||||
og.sort(function(a, b) { return parseInt(b[2]) - parseInt(a[2]) });
|
||||
|
||||
for (var i = 0; i < og.length; i++)
|
||||
{
|
||||
var tr = t.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row cbi-rowstyle-' + (1 + (i % 2));
|
||||
|
||||
var icon;
|
||||
if (og[i][2] < 64)
|
||||
icon = "<%=resource%>/icons/signal-0-25.png";
|
||||
else if (og[i][2] < 128)
|
||||
icon = "<%=resource%>/icons/signal-25-50.png";
|
||||
else if (og[i][2] < 192)
|
||||
icon = "<%=resource%>/icons/signal-50-75.png";
|
||||
else
|
||||
icon = "<%=resource%>/icons/signal-75-100.png";
|
||||
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<img src="%s" title="<%:Quality%>: %d / 255" style="vertical-align:middle" /> %d/255',
|
||||
icon, og[i][2], og[i][2]
|
||||
);
|
||||
|
||||
if ( og[i][3] == "Here" )
|
||||
{
|
||||
tr.insertCell(-1).innerHTML = '<strong>' + og[i][0] + '</strong>' ;
|
||||
og[i][3] = " ";
|
||||
}
|
||||
else
|
||||
{
|
||||
tr.insertCell(-1).innerHTML = og[i][0];
|
||||
}
|
||||
tr.insertCell(-1).innerHTML = String.format('%dms', og[i][1]);
|
||||
tr.insertCell(-1).innerHTML = og[i][4];
|
||||
tr.insertCell(-1).innerHTML = og[i][3];
|
||||
}
|
||||
|
||||
if (t.rows.length == 1)
|
||||
{
|
||||
var tr = t.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row';
|
||||
|
||||
var td = tr.insertCell(-1);
|
||||
td.colSpan = 3;
|
||||
td.innerHTML = '<br /><em><%:There are no active neighbors%></em>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!!(t = document.getElementById('gateway_table')))
|
||||
{
|
||||
/* clear all rows */
|
||||
while (t.rows.length > 1)
|
||||
t.rows[0].parentNode.deleteRow(1);
|
||||
|
||||
gw.sort(function(a, b) { return a[0] > b[0] });
|
||||
|
||||
for (var i = 0; i < gw.length; i++)
|
||||
{
|
||||
var tr = t.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row cbi-rowstyle-' + (1 + (i % 2));
|
||||
|
||||
tr.insertCell(-1).innerHTML = gw[i][0]
|
||||
? String.format('<strong>%s (active)</strong>', gw[i][1])
|
||||
: gw[i][1];
|
||||
|
||||
tr.insertCell(-1).innerHTML = gw[i][6];
|
||||
tr.insertCell(-1).innerHTML = String.format('%d/255', gw[i][2]);
|
||||
tr.insertCell(-1).innerHTML = gw[i][4];
|
||||
tr.insertCell(-1).innerHTML = gw[i][3];
|
||||
}
|
||||
|
||||
if (t.rows.length == 1)
|
||||
{
|
||||
var tr = t.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row';
|
||||
|
||||
var td = tr.insertCell(-1);
|
||||
td.colSpan = 3;
|
||||
td.innerHTML = '<br /><em><%:There are no active mesh gateways%></em>';
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("batman/topo/json")%>', null,
|
||||
function(x, data)
|
||||
{
|
||||
var g = new Graph();
|
||||
|
||||
|
||||
var render = function(r, node) {
|
||||
var color = Raphael.getColor();
|
||||
var rect = r.rect(node.point[0]-50, node.point[1]-10, 100, 20)
|
||||
.attr({"fill": color, "stroke": color, "stroke-width": 2, r : "9px"})
|
||||
var set = r.set().
|
||||
push(rect).
|
||||
push(r.text(node.point[0], node.point[1], node.label || node.id)
|
||||
.attr({"fill": "#000"}));
|
||||
return set;
|
||||
};
|
||||
|
||||
for (var i = 0; i < (data.length-1); i++)
|
||||
{
|
||||
// node->node
|
||||
if (data[i].router && data[i].neighbor) {
|
||||
g.addNode(data[i].router, { render: render });
|
||||
g.addNode(data[i].neighbor, { render: render });
|
||||
g.addEdge(data[i].router, data[i].neighbor,
|
||||
{ label: parseFloat(data[i].label).toFixed(1),
|
||||
directed: true, stroke: '#aaaaaa' });
|
||||
}
|
||||
else if (data[i].secondary) {
|
||||
g.addNode(data[i].secondary, { render: render });
|
||||
g.addNode(data[i].of, { render: render });
|
||||
g.addEdge(data[i].secondary, data[i].of,
|
||||
{ fill: "#000" } );
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('canvas').innerHTML = "";
|
||||
var canvas = document.getElementById('canvas');
|
||||
|
||||
var layouter = new Graph.Layout.Spring(g);
|
||||
layouter.layout();
|
||||
|
||||
var renderer = new Graph.Renderer.Raphael(canvas.id, g, canvas.offsetWidth, canvas.offsetHeight);
|
||||
renderer.draw();
|
||||
}
|
||||
);
|
||||
|
||||
XHR.poll(25, '<%=luci.dispatcher.build_url("batman/topo/json")%>', null,
|
||||
function(x, data)
|
||||
{
|
||||
var g = new Graph();
|
||||
|
||||
|
||||
var render = function(r, node) {
|
||||
var color = Raphael.getColor();
|
||||
var rect = r.rect(node.point[0]-50, node.point[1]-10, 100, 20)
|
||||
.attr({"fill": color, "stroke": color, "stroke-width": 2, r : "9px"})
|
||||
var set = r.set().
|
||||
push(rect).
|
||||
push(r.text(node.point[0], node.point[1], node.label || node.id)
|
||||
.attr({"fill": "#000"}));
|
||||
return set;
|
||||
};
|
||||
|
||||
for (var i = 0; i < (data.length-1); i++)
|
||||
{
|
||||
// node->node
|
||||
if (data[i].router && data[i].neighbor) {
|
||||
g.addNode(data[i].router, { render: render });
|
||||
g.addNode(data[i].neighbor, { render: render });
|
||||
g.addEdge(data[i].router, data[i].neighbor,
|
||||
{ label: parseFloat(data[i].label).toFixed(1),
|
||||
directed: true, stroke: '#aaaaaa' });
|
||||
}
|
||||
else if (data[i].secondary) {
|
||||
g.addNode(data[i].secondary, { render: render });
|
||||
g.addNode(data[i].of, { render: render });
|
||||
g.addEdge(data[i].secondary, data[i].of,
|
||||
{ fill: "#000" } );
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('canvas').innerHTML = "";
|
||||
var canvas = document.getElementById('canvas');
|
||||
|
||||
var layouter = new Graph.Layout.Spring(g);
|
||||
layouter.layout();
|
||||
|
||||
var renderer = new Graph.Renderer.Raphael(canvas.id, g, canvas.offsetWidth, canvas.offsetHeight);
|
||||
renderer.draw();
|
||||
}
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<h2><a id="content" name="content"><%:Mesh Status%></a></h2>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<table width="550" border="0">
|
||||
<tr>
|
||||
<td width="17%"><div align="right"><strong>Internet Status : </strong></div></td>
|
||||
<td width="19%"><ul id="status"></ul></td>
|
||||
<td width="65%"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Active Mesh Nodes%></legend>
|
||||
<table class="cbi-section-table" id="originator_table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:Link Quality%></th>
|
||||
<th class="cbi-section-table-cell"><%:MAC-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:Last Seen%></th>
|
||||
<th class="cbi-section-table-cell"><%:Interface%></th>
|
||||
<th class="cbi-section-table-cell"><%:Next Hop%></th>
|
||||
</tr>
|
||||
<tr class="cbi-section-table-row">
|
||||
<td colspan="3"><em><br /><%:Collecting data...%></em></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Other Mesh Nodes with Internet Access%></legend>
|
||||
<table class="cbi-section-table" id="gateway_table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:MAC-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:Speed%></th>
|
||||
<th class="cbi-section-table-cell"><%:Link Quality%></th>
|
||||
<th class="cbi-section-table-cell"><%:Interface%></th>
|
||||
<th class="cbi-section-table-cell"><%:Next Hop%></th>
|
||||
</tr>
|
||||
<tr class="cbi-section-table-row">
|
||||
<td colspan="3"><em><br /><%:Collecting data...%></em></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Visualization%></legend>
|
||||
<div id="canvas" style="min-width:800px; min-height:600px"></div>
|
||||
</fieldset>
|
||||
|
||||
<%+footer%>
|
@ -0,0 +1,912 @@
|
||||
<%+header%>
|
||||
<%
|
||||
local sys = require "luci.sys"
|
||||
local utl = require "luci.util"
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
function showicon(lck)
|
||||
if lck == 0 then
|
||||
return resource .. "/icons/unlock1.png"
|
||||
else
|
||||
return resource .. "/icons/lock1.png"
|
||||
end
|
||||
end
|
||||
|
||||
-%>
|
||||
<script type="text/javascript" src="<%=resource%>/xhr.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
var change=0;
|
||||
var radnum = 1; // radio number option radionumber '0'
|
||||
var channelindex = 0 ; // index in to list option channelindex '0'
|
||||
var channellist = 0; // list number 0-2 option channellist "0"
|
||||
var channelwidth = 1; // index of bw 0-3 option channelwidth '0'
|
||||
var usedfs = 0; // 1 is dfs channels option usedfs "0"
|
||||
var detecatedradio = 1; // 1 is dedicated radio option dedicated "0"
|
||||
|
||||
var networkid = "MeshCloud";
|
||||
var netencrypted = 0;
|
||||
var netpassword = "password";
|
||||
|
||||
var signalenable = 1;
|
||||
var signalid = "mesh";
|
||||
|
||||
var radiolist = new Array() ;
|
||||
var partsArray = new Array;
|
||||
var channels = new Array;
|
||||
var cwidth = ["20", "40", "80", "80"];
|
||||
var channelnum = 0;
|
||||
var chan2num = 14;
|
||||
var chan5num = 10;
|
||||
var chan5dfsnum = 23;
|
||||
var channel2 = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14" ];
|
||||
var channel5 = ["36", "40", "44", "48", "149", "153", "157", "161", "165", "169"];
|
||||
var channel5dfs = ["36", "40", "44", "48", "52", "56", "60", "64", "100", "104", "104", "112", "116", "132", "136", "140", "144", "149", "153", "157", "161", "165", "169"];
|
||||
|
||||
function setwidth(width)
|
||||
{
|
||||
switch (width)
|
||||
{
|
||||
case "0":
|
||||
num = 1;
|
||||
dropname = "drop5";
|
||||
break;
|
||||
case "1":
|
||||
num = 2;
|
||||
dropname = "drop6";
|
||||
break;
|
||||
case "2":
|
||||
num = 3;
|
||||
dropname = "drop7";
|
||||
break;
|
||||
case "3":
|
||||
num = 3;
|
||||
dropname = "drop8";
|
||||
break;
|
||||
}
|
||||
x = document.getElementById(dropname);
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
option = document.createElement("option");
|
||||
option.text = cwidth[i] + "Mhz";
|
||||
x.add(option);
|
||||
}
|
||||
}
|
||||
|
||||
function changebw(flg)
|
||||
{
|
||||
partsArray = radiolist[radnum].split('|');
|
||||
channelw = partsArray[2];
|
||||
|
||||
switch (channelw)
|
||||
{
|
||||
case "0":
|
||||
document.getElementById("radio46").style.visibility="visible";
|
||||
if ( flg == 1 )
|
||||
{
|
||||
document.getElementById("radio46").style.display = "";
|
||||
}
|
||||
document.getElementById("drop5").selectedIndex = channelwidth;
|
||||
document.getElementById("radio47").style.display = "none";
|
||||
document.getElementById("radio47").style.visibility="hidden";
|
||||
document.getElementById("radio48").style.display = "none";
|
||||
document.getElementById("radio48").style.visibility="hidden";
|
||||
document.getElementById("radio49").style.display = "none";
|
||||
document.getElementById("radio49").style.visibility="hidden";
|
||||
break;
|
||||
case "1":
|
||||
document.getElementById("radio47").style.visibility="visible";
|
||||
if ( flg == 1 )
|
||||
{
|
||||
document.getElementById("radio47").style.display = "";
|
||||
}
|
||||
document.getElementById("drop6").selectedIndex = channelwidth;
|
||||
document.getElementById("radio46").style.display = "none";
|
||||
document.getElementById("radio46").style.visibility="hidden";
|
||||
document.getElementById("radio48").style.display = "none";
|
||||
document.getElementById("radio48").style.visibility="hidden";
|
||||
document.getElementById("radio49").style.display = "none";
|
||||
document.getElementById("radio49").style.visibility="hidden";
|
||||
break;
|
||||
case "2":
|
||||
document.getElementById("radio48").style.visibility="visible";
|
||||
if ( flg == 1 )
|
||||
{
|
||||
document.getElementById("radio48").style.display = "";
|
||||
}
|
||||
document.getElementById("drop7").selectedIndex = channelwidth;
|
||||
document.getElementById("radio46").style.display = "none";
|
||||
document.getElementById("radio46").style.visibility="hidden";
|
||||
document.getElementById("radio47").style.display = "none";
|
||||
document.getElementById("radio47").style.visibility="hidden";
|
||||
document.getElementById("radio49").style.display = "none";
|
||||
document.getElementById("radio49").style.visibility="hidden";
|
||||
break;
|
||||
case "3":
|
||||
document.getElementById("radio49").style.visibility="visible";
|
||||
if ( flg == 1 )
|
||||
{
|
||||
document.getElementById("radio49").style.display = "";
|
||||
}
|
||||
document.getElementById("drop8").selectedIndex = channelwidth;
|
||||
document.getElementById("radio46").style.display = "none";
|
||||
document.getElementById("radio46").style.visibility="hidden";
|
||||
document.getElementById("radio47").style.display = "none";
|
||||
document.getElementById("radio47").style.visibility="hidden";
|
||||
document.getElementById("radio48").style.display = "none";
|
||||
document.getElementById("radio48").style.visibility="hidden";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function vischannel(flg)
|
||||
{
|
||||
partsArray = radiolist[radnum].split('|');
|
||||
if ( partsArray[0] == "1" )
|
||||
{
|
||||
document.getElementById("radio3").style.display = "none";
|
||||
document.getElementById("radio3").style.visibility="hidden";
|
||||
document.getElementById("radio33").style.display = "none";
|
||||
document.getElementById("radio33").style.visibility="hidden";
|
||||
document.getElementById("drop2").style.display = "none";
|
||||
document.getElementById("drop2").style.visibility="hidden";
|
||||
|
||||
if ( usedfs == 0 )
|
||||
{
|
||||
document.getElementById("radio4").style.display = "block";
|
||||
document.getElementById("radio4").style.visibility="visible";
|
||||
document.getElementById("drop3").style.display = "block";
|
||||
document.getElementById("drop3").style.visibility="visible";
|
||||
document.getElementById("radio44").style.visibility="visible";
|
||||
if ( flg == 1 )
|
||||
{
|
||||
document.getElementById("radio44").style.display = "";
|
||||
}
|
||||
channellist = 1;
|
||||
document.getElementById("drop3").selectedIndex = channelindex;
|
||||
|
||||
document.getElementById("radio5").style.display = "none";
|
||||
document.getElementById("radio5").style.visibility="hidden";
|
||||
document.getElementById("drop4").style.display = "none";
|
||||
document.getElementById("drop4").style.visibility="hidden";
|
||||
document.getElementById("radio55").style.display = "none";
|
||||
document.getElementById("radio55").style.visibility="hidden";
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById("radio5").style.display = "block";
|
||||
document.getElementById("radio5").style.visibility="visible";
|
||||
document.getElementById("drop4").style.display = "block";
|
||||
document.getElementById("drop4").style.visibility="visible";
|
||||
document.getElementById("radio55").style.visibility="visible";
|
||||
if ( flg == 1 )
|
||||
{
|
||||
document.getElementById("radio55").style.display = "";
|
||||
}
|
||||
channellist = 2;
|
||||
document.getElementById("drop4").selectedIndex = channelindex;
|
||||
|
||||
document.getElementById("radio4").style.display = "none";
|
||||
document.getElementById("radio4").style.visibility="hidden";
|
||||
document.getElementById("drop3").style.display = "none";
|
||||
document.getElementById("drop3").style.visibility="hidden";
|
||||
document.getElementById("radio44").style.display = "none";
|
||||
document.getElementById("radio44").style.visibility="hidden";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById("radio3").style.display = "block";
|
||||
document.getElementById("radio3").style.visibility="visible";
|
||||
document.getElementById("radio33").style.visibility="visible";
|
||||
if ( flg == 1 )
|
||||
{
|
||||
document.getElementById("radio33").style.display = "";
|
||||
}
|
||||
channellist = 0;
|
||||
document.getElementById("drop2").style.display = "block";
|
||||
document.getElementById("drop2").style.visibility="visible";
|
||||
document.getElementById("drop2").selectedIndex = channelindex;
|
||||
|
||||
document.getElementById("radio4").style.display = "none";
|
||||
document.getElementById("radio4").style.visibility="hidden";
|
||||
document.getElementById("drop3").style.display = "none";
|
||||
document.getElementById("drop3").style.visibility="hidden";
|
||||
document.getElementById("radio44").style.display = "none";
|
||||
document.getElementById("radio44").style.visibility="hidden";
|
||||
|
||||
document.getElementById("radio5").style.display = "none";
|
||||
document.getElementById("radio5").style.visibility="hidden";
|
||||
document.getElementById("drop4").style.display = "none";
|
||||
document.getElementById("drop4").style.visibility="hidden";
|
||||
document.getElementById("radio55").style.display = "none";
|
||||
document.getElementById("radio55").style.visibility="hidden";
|
||||
}
|
||||
}
|
||||
|
||||
function setchannels(freq)
|
||||
{
|
||||
switch ( freq )
|
||||
{
|
||||
case "0" :
|
||||
channels = channel2;
|
||||
chansize = chan2num;
|
||||
dropname = "drop2";
|
||||
break;
|
||||
case "1" :
|
||||
channels = channel5;
|
||||
chansize = chan5num;
|
||||
dropname = "drop3";
|
||||
break;
|
||||
case "2" :
|
||||
channels = channel5dfs;
|
||||
chansize = chan5dfsnum;
|
||||
dropname = "drop4";
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
x = document.getElementById(dropname);
|
||||
for (i = 0; i < chansize; i++)
|
||||
{
|
||||
option = document.createElement("option");
|
||||
option.text = "Channel " + channels[i];
|
||||
x.add(option);
|
||||
}
|
||||
x.selectedIndex = channelnum;
|
||||
}
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "mesh", "getstate")%>',
|
||||
null,
|
||||
function(x, rv)
|
||||
{
|
||||
document.getElementById("cbi-modw").style.display = "none";
|
||||
document.getElementById("cbi-modw").style.visibility="hidden";
|
||||
document.getElementById("cbi-mod1").style.display = "block";
|
||||
document.getElementById("cbi-mod1").style.visibility="visible";
|
||||
document.getElementById("cbi-mod2").style.display = "block";
|
||||
document.getElementById("cbi-mod2").style.visibility="visible";
|
||||
document.getElementById("cbi-mod3").style.display = "block";
|
||||
document.getElementById("cbi-mod3").style.visibility="visible";
|
||||
|
||||
radnum = parseInt(rv.radionumber);
|
||||
channelindex = parseInt(rv.channelindex);
|
||||
channellist = parseInt(rv.channellist);
|
||||
channelwidth = parseInt(rv.channelwidth);
|
||||
usedfs = parseInt(rv.usedfs);
|
||||
detecatedradio = parseInt(rv.dedicated);
|
||||
|
||||
networkid = rv.networkid;
|
||||
netencrypted = parseInt(rv.netencrypted);
|
||||
netpassword = rv.netpassword;
|
||||
|
||||
signalenable = parseInt(rv.signalenable);
|
||||
signalid = rv.signalid;
|
||||
|
||||
document.getElementById("dedicated").checked = false;
|
||||
if ( detecatedradio == 1 )
|
||||
{
|
||||
document.getElementById("dedicated").checked = true;
|
||||
}
|
||||
document.getElementById("dfs").checked = false;
|
||||
document.getElementById("dfs3").checked = false;
|
||||
if ( usedfs == 1)
|
||||
{
|
||||
document.getElementById("dfs").checked = true;
|
||||
document.getElementById("dfs3").checked = true;
|
||||
}
|
||||
|
||||
num_radio = parseInt(rv.radio);
|
||||
if ( num_radio > 0 )
|
||||
{
|
||||
radiolist = rv.radiolist;
|
||||
x = document.getElementById("drop1");
|
||||
for (i = 0; i < num_radio; i++)
|
||||
{
|
||||
partsArray = radiolist[i].split('|');
|
||||
dropradio = "Radio" + partsArray[1];
|
||||
if ( partsArray[0] == "1" )
|
||||
{
|
||||
dropradio = dropradio + " (5Ghz)";
|
||||
}
|
||||
else
|
||||
{
|
||||
dropradio = dropradio + " (2.4Ghz)";
|
||||
}
|
||||
option = document.createElement("option");
|
||||
option.text = dropradio;
|
||||
x.add(option);
|
||||
}
|
||||
x.selectedIndex = radnum;
|
||||
setchannels("0");
|
||||
setchannels("1");
|
||||
setchannels("2");
|
||||
setwidth("0");
|
||||
setwidth("1");
|
||||
setwidth("2");
|
||||
setwidth("3");
|
||||
vischannel(0);
|
||||
changebw(0);
|
||||
|
||||
document.getElementById("idnam").value = networkid;
|
||||
document.getElementById("encr").checked = false;
|
||||
document.getElementById("enc2").style.display = "none";
|
||||
document.getElementById("enc2").style.visibility="hidden";
|
||||
document.getElementById("netpass").style.display = "none";
|
||||
document.getElementById("netpass").style.visibility="hidden";
|
||||
if ( netencrypted == 1 )
|
||||
{
|
||||
document.getElementById("encr").checked = true;
|
||||
document.getElementById("enc2").style.display = "block";
|
||||
document.getElementById("enc2").style.visibility="visible";
|
||||
document.getElementById("netpass").style.display = "block";
|
||||
document.getElementById("netpass").style.visibility="visible";
|
||||
}
|
||||
document.getElementById("netpass").value = netpassword;
|
||||
|
||||
document.getElementById("sigenb").checked = false;
|
||||
document.getElementById("roam11").style.display = "none";
|
||||
document.getElementById("roam11").style.visibility="hidden";
|
||||
|
||||
document.getElementById("idsig").value = signalid;
|
||||
|
||||
if ( signalenable == 1 )
|
||||
{
|
||||
document.getElementById("sigenb").checked = true;
|
||||
document.getElementById("roam11").style.display = "";
|
||||
document.getElementById("roam11").style.visibility="visible";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
);
|
||||
function changes(value)
|
||||
{
|
||||
change = value;
|
||||
if ( value == 0 )
|
||||
{
|
||||
document.getElementById("meshstat1").innerHTML = "No Changes";
|
||||
document.getElementById("meshstat1").style.color = "inherit";
|
||||
document.getElementById("meshstat1").style.fontWeight = "bold" ;
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById("meshstat1").innerHTML = "Unsaved Changes";
|
||||
document.getElementById("meshstat1").style.color = "red";
|
||||
document.getElementById("meshstat1").style.fontWeight = "bold" ;
|
||||
}
|
||||
}
|
||||
|
||||
function radiochange(drop)
|
||||
{
|
||||
radnum = document.getElementById("drop1").selectedIndex;
|
||||
channelindex = 0;
|
||||
vischannel(1);
|
||||
channelwidth = 0;
|
||||
changebw(1);
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function dedicatedrad(check)
|
||||
{
|
||||
if ( check.checked == true )
|
||||
{
|
||||
detecatedradio = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
detecatedradio = 0;
|
||||
}
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function setdfs(check)
|
||||
{
|
||||
if ( check.checked == true )
|
||||
{
|
||||
usedfs = 1;
|
||||
radiochange();
|
||||
document.getElementById("dfs").checked = true;
|
||||
document.getElementById("dfs3").checked = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
usedfs = 0;
|
||||
radiochange();
|
||||
document.getElementById("dfs").checked = false;
|
||||
document.getElementById("dfs3").checked = false;
|
||||
}
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function bwchange(bwbox)
|
||||
{
|
||||
bw = bwbox.selectedIndex;
|
||||
channelwidth = bw;
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function channelchange(chn)
|
||||
{
|
||||
channelindex = chn.selectedIndex;
|
||||
radnum = document.getElementById("drop1").selectedIndex;
|
||||
partsArray = radiolist[radnum].split('|');
|
||||
if ( partsArray[0] == "1" )
|
||||
{
|
||||
channellist = 1;
|
||||
if ( usedfs == 1 )
|
||||
{
|
||||
channellist = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
channellist = 0;
|
||||
}
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function setencr(check)
|
||||
{
|
||||
if ( check.checked == true )
|
||||
{
|
||||
document.getElementById("enc2").style.display = "block";
|
||||
document.getElementById("enc2").style.visibility="visible";
|
||||
document.getElementById("netpass").style.display = "block";
|
||||
document.getElementById("netpass").style.visibility="visible";
|
||||
netencrypted = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById("enc2").style.display = "none";
|
||||
document.getElementById("enc2").style.visibility="hidden";
|
||||
document.getElementById("netpass").style.display = "none";
|
||||
document.getElementById("netpass").style.visibility="hidden";
|
||||
netencrypted = 0;
|
||||
}
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function setlow(check)
|
||||
{
|
||||
if ( check.checked == true )
|
||||
{
|
||||
document.getElementById("roam11").style.display = "";
|
||||
document.getElementById("roam11").style.visibility="visible";
|
||||
signalenable = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById("roam11").style.display = "none";
|
||||
document.getElementById("roam11").style.visibility="hidden";
|
||||
signalenable = 0;
|
||||
}
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function changeid()
|
||||
{
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function changesigid()
|
||||
{
|
||||
signalid = document.getElementById("idsig").value ;
|
||||
if ( !signalid )
|
||||
{
|
||||
document.getElementById("idsig").value = 'abcd' ;
|
||||
signalid = 'abcd';
|
||||
}
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function configup(btn)
|
||||
{
|
||||
var filex = btn.files[0];
|
||||
var reader = new FileReader();
|
||||
reader.readAsText(filex);
|
||||
reader.onload = loaded;
|
||||
}
|
||||
|
||||
function loaded(evt)
|
||||
{
|
||||
var fileString = evt.target.result;
|
||||
partsArray = fileString.split('|');
|
||||
if ( partsArray[0] == "meshcfg" )
|
||||
{
|
||||
radionumber = parseInt(partsArray[0]);
|
||||
channelindex = parseInt(partsArray[1]);
|
||||
channellist = parseInt(partsArray[2]);
|
||||
usedfs = parseInt(partsArray[3]);
|
||||
channelwidth = parseInt(partsArray[4]);
|
||||
detecatedradio = parseInt(partsArray[5]);
|
||||
networkid=partsArray[6];
|
||||
netencrypted = parseInt(partsArray[7]);
|
||||
netpassword=partsArray[8];
|
||||
signalenable = parseInt(partsArray[9]);
|
||||
signalmeasure = parseInt(partsArray[10]);
|
||||
signalinterval = parseInt(partsArray[11]);
|
||||
signalcount = parseInt(partsArray[12]);
|
||||
snrconnect = parseInt(partsArray[13]);
|
||||
snrchange = parseInt(partsArray[14]);
|
||||
sigconnect = parseInt(partsArray[15]);
|
||||
sigchange = parseInt(partsArray[16]);
|
||||
window.location.reload(false);
|
||||
}
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function buildsave()
|
||||
{
|
||||
netpassword = document.getElementById("netpass").value;
|
||||
if ( netencrypted == 1 )
|
||||
{
|
||||
if ( netpassword.length < 8 )
|
||||
{
|
||||
alert("You must enter a password at least 8 charactets long!!");
|
||||
return "1";
|
||||
}
|
||||
}
|
||||
if ( netpassword.length < 8 )
|
||||
{
|
||||
netpassword="password";
|
||||
}
|
||||
|
||||
var stat = radnum.toString() + "|" + channelindex.toString() + "|" + channellist.toString() + "|" + usedfs.toString() + "|" + channelwidth.toString() + "|" + detecatedradio.toString() + "|" + networkid + "|" + netencrypted.toString() + "|" + netpassword + "|" ;
|
||||
|
||||
var rom = signalenable.toString() + "|" + signalid + "|" ;
|
||||
|
||||
stat = stat + rom;
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
function saveconf(btn)
|
||||
{
|
||||
statusm = buildsave();
|
||||
if ( statusm == "1" )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
statusm = "meshcfg|" + statusm;
|
||||
|
||||
//document.getElementById("attxt").value=statusm;
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "mesh", "meshcfg")%>',
|
||||
{ set: statusm },
|
||||
function()
|
||||
{
|
||||
window.open('http://'+window.location.hostname+'/package/meshcfg.meshcfg', '_self')
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function savemesh(btn)
|
||||
{
|
||||
statusm = buildsave();
|
||||
if ( statusm == "1" )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "mesh", "sendmeshstate")%>',
|
||||
{ set: statusm },
|
||||
function()
|
||||
{
|
||||
window.location.reload(false);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function reloadmesh()
|
||||
{
|
||||
changes(0);
|
||||
window.location.reload(false);
|
||||
}
|
||||
|
||||
var tries = 0,
|
||||
message = document.querySelector('p.reboot-message'),
|
||||
label = message.querySelector('span');
|
||||
|
||||
function ok() {
|
||||
window.location = '<%=url("admin")%>';
|
||||
}
|
||||
|
||||
function check() {
|
||||
window.setTimeout(ping, 5000);
|
||||
}
|
||||
|
||||
function ping() {
|
||||
var img = document.createElement('img');
|
||||
|
||||
img.onload = ok;
|
||||
img.onerror = check;
|
||||
img.src = '<%=resource%>/icons/loading.gif?' + Math.random();
|
||||
|
||||
if (tries++ >= 30) {
|
||||
message.classList.remove('notice');
|
||||
message.classList.add('warning');
|
||||
label.innerHTML = '<%:Device unreachable! Still waiting for device...%>';
|
||||
}
|
||||
}
|
||||
|
||||
function startstopmesh(btn)
|
||||
{
|
||||
if (change == 1 )
|
||||
{
|
||||
savech = confirm("Unsaved changes will be lost. Save first?");
|
||||
if ( savech == true )
|
||||
{
|
||||
statusm = buildsave();
|
||||
if ( statusm !== "1" )
|
||||
{
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "mesh", "sendmeshstate")%>',
|
||||
{ set: statusm },
|
||||
function()
|
||||
{
|
||||
}
|
||||
);
|
||||
changes(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
cont = confirm("Router will reboot after applying settings. Continue?");
|
||||
if ( cont == false )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
document.getElementById("cbi-modw").style.display = "block";
|
||||
document.getElementById("cbi-modw").style.visibility="visible";
|
||||
document.getElementById("cbi-mod1").style.display = "none";
|
||||
document.getElementById("cbi-mod1").style.visibility="hidden";
|
||||
document.getElementById("cbi-mod2").style.display = "none";
|
||||
document.getElementById("cbi-mod2").style.visibility="hidden";
|
||||
document.getElementById("cbi-mod3").style.display = "none";
|
||||
document.getElementById("cbi-mod3").style.visibility="hidden";
|
||||
document.getElementById("fileup").disabled=true;
|
||||
document.getElementById("meshconf").disabled=true;
|
||||
document.getElementById("meshsave").disabled=true;
|
||||
document.getElementById("meshstart").disabled=true;
|
||||
document.getElementById("meshstat1").style.display = "none";
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "mesh", "meshstartstop")%>',
|
||||
{ set: "1" },
|
||||
function()
|
||||
{
|
||||
}
|
||||
);
|
||||
check();
|
||||
}
|
||||
|
||||
//document.getElementById("attxt").value=partsArray[0].toString();
|
||||
|
||||
//]]></script>
|
||||
|
||||
<form method="post" action="<%=REQUEST_URI%>">
|
||||
<div class="cbi-map" id="cbi-modem">
|
||||
<h2><a id="content" name="content">Mesh Network Configuration</a></h2>
|
||||
<div class="cbi-map-descr"> </div>
|
||||
|
||||
<fieldset class="cbi-section" id="cbi-mod">
|
||||
|
||||
<table width="100%" border="0" id="meshstatus">
|
||||
<tr>
|
||||
<td width="20%"><div align="center" id="meshstat2" style="font-size:1.5em"><strong>Config Status</strong></div></td>
|
||||
<td width="20%"><div align="center" id="upl2" ><strong>Import Configuration File</strong></div></td>
|
||||
<td width="13%"><div align="center" id="upl3" ><strong>Export Configuration File</strong></div></td>
|
||||
<td width="10%"><div align="center" id="up42" ><strong>Save Settings</strong></div></td>
|
||||
<td width="10%"><div align="center" id="up52" ><strong>Apply Settings</strong></div></td>
|
||||
<td width="10%"><div align="center" id="up52" ><strong>Reload Settings</strong></div></td>
|
||||
<td width="17%"></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="20%"><div align="center" id="meshstat1" ><strong>No Changes</strong></div></td>
|
||||
<td width="20%"><input type="file" accept=".meshcfg" align="center" name="fileup" id="fileup" class="cbi-button cbi-button-positive" onchange="return configup(this)" /></td>
|
||||
<td width="13%"><input type="button" align="center" id="meshconf" class="cbi-button cbi-button-positive" value="<%:Save Configuration File%>" onclick="return saveconf(this)" /></td>
|
||||
<td width="10%"><input type="button" align="center" id="meshsave" class="cbi-button cbi-button-positive" value="<%:Save Settings%>" onclick="return savemesh(this)" /></td>
|
||||
<td width="10%"><input type="button" align="center" id="meshstart" class="cbi-button cbi-button-positive" value="<%:Apply Settings%>" onclick="return startstopmesh(this)" /></td>
|
||||
<td width="10%"><input type="button" align="center" id="meshreload" class="cbi-button cbi-button-positive" value="<%:Reload Settings%>" onclick="return reloadmesh(this)" /></td>
|
||||
<td width="17%"></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section" id="cbi-modw" style="visibility:hidden">
|
||||
<table width="100%" cellspacing="10" id="waiting">
|
||||
<tr>
|
||||
<td width="40%"></td>
|
||||
<td id="waiticon"><img src="<%=resource%>/icons/loading.gif" style="vertical-align:middle" /> Waiting for Reboot...</td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section" id="cbi-mod1">
|
||||
<table width="100%" border="0" id="meshradio" >
|
||||
<tr>
|
||||
<td width="17%"><div align="left" id="radio1" style="font-size:1.5em"><strong>Mesh Radio Settings</strong></div></td>
|
||||
<td width="15%"></td>
|
||||
<td width="12%"></td>
|
||||
<td width="5%"></td>
|
||||
<td width="20%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="17%"><div align="right" id="radio2" ><strong>Select Backhaul Radio </strong></div></td>
|
||||
<td width="15%">
|
||||
<select style="width:200px" name="raddrop" id="drop1" onchange="return radiochange(this)">
|
||||
</select>
|
||||
</td>
|
||||
<td width="12%"><div align="left" id="dedicated1" style="font-size:1em"><strong>Dedicated Backhaul Radio </strong></div></td>
|
||||
<td width="5%"><input type="checkbox" id="dedicated" onclick="return dedicatedrad(this)" /></td>
|
||||
<td width="20%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr id="radio33">
|
||||
<td width="17%"><div align="right" id="radio3" ><strong>Select Backhaul Channel </strong></div></td>
|
||||
<td width="15%">
|
||||
<select style="width:200px" name="chandrop" id="drop2" onchange="return channelchange(this)">
|
||||
</select>
|
||||
</td>
|
||||
<td width="12%"></td>
|
||||
<td width="5%"></td>
|
||||
<td width="20%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr id="radio44">
|
||||
<td width="17%"><div align="right" id="radio4" ><strong>Select Backhaul Channel </strong></div></td>
|
||||
<td width="15%">
|
||||
<select style="width:200px" name="chandrop1" id="drop3" onchange="return channelchange(this)">
|
||||
</select>
|
||||
</td>
|
||||
<td width="12%"><div align="left" id="dfs1" style="font-size:1em"><strong>Use DFS Channels </strong></div></td>
|
||||
<td width="5%"><input type="checkbox" id="dfs" onclick="return setdfs(this)" /></td>
|
||||
<td width="20%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr id="radio55">
|
||||
<td width="17%"><div align="right" id="radio5" ><strong>Select Backhaul Channel </strong></div></td>
|
||||
<td width="15%">
|
||||
<select style="width:200px" name="chandrop2" id="drop4" onchange="return channelchange(this)">
|
||||
</select>
|
||||
</td>
|
||||
<td width="12%"><div align="left" id="dfs2" style="font-size:1em"><strong>Use DFS Channels </strong></div></td>
|
||||
<td width="5%"><input type="checkbox" id="dfs3" onclick="return setdfs(this)" /></td>
|
||||
<td width="20%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr id="radio46">
|
||||
<td width="17%"><div align="right" id="radio6" ><strong>Channel Bandwidth </strong></div></td>
|
||||
<td width="15%">
|
||||
<select style="width:200px" name="chandrop3" id="drop5" onchange="return bwchange(this)">
|
||||
</select>
|
||||
</td>
|
||||
<td width="12%"></td>
|
||||
<td width="5%"></td>
|
||||
<td width="20%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr id="radio47">
|
||||
<td width="17%"><div align="right" id="radio7" ><strong>Channel Bandwidth </strong></div></td>
|
||||
<td width="15%">
|
||||
<select style="width:200px" name="chandrop3" id="drop6" onchange="return bwchange(this)">
|
||||
</select>
|
||||
</td>
|
||||
<td width="12%"></td>
|
||||
<td width="5%"></td>
|
||||
<td width="20%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr id="radio48">
|
||||
<td width="17%"><div align="right" id="radio7" ><strong>Channel Bandwidth </strong></div></td>
|
||||
<td width="15%">
|
||||
<select style="width:200px" name="chandrop3" id="drop7" onchange="return bwchange(this)">
|
||||
</select>
|
||||
</td>
|
||||
<td width="12%"></td>
|
||||
<td width="5%"></td>
|
||||
<td width="20%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr id="radio49">
|
||||
<td width="17%"><div align="right" id="radio7" ><strong>Channel Bandwidth </strong></div></td>
|
||||
<td width="15%">
|
||||
<select style="width:200px" name="chandrop3" id="drop8" onchange="return bwchange(this)">
|
||||
</select>
|
||||
</td>
|
||||
<td width="12%"></td>
|
||||
<td width="5%"></td>
|
||||
<td width="20%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section" id="cbi-mod2" >
|
||||
<table width="100%" border="0" id="meshnet" >
|
||||
<tr>
|
||||
<td width="17%"><div align="left" id="net1" style="font-size:1.5em"><strong>Mesh Network Settings</strong></div></td>
|
||||
<td width="10%"></td>
|
||||
<td width="12%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="17%"><div align="right" id="net2" ><strong>Mesh Network ID </strong></div></td>
|
||||
<td width="10%" ><input style="width: 200px;" type="text" name="idnam" id="idnam" class="cbi-input-text" value="MeshCloud" onchange="return changeid()" ></input></td>
|
||||
<td width="12%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="17%"><div align="right" id="enc1" style="font-size:1em"><strong>Network Encrypted </strong></div></td>
|
||||
<td width="10%"><input type="checkbox" id="encr" onclick="return setencr(this)" /></td>
|
||||
<td width="12%"><div align="left" id="enc2" style="font-size:1em; visibility:hidden"><strong>Network Password </strong></div></td>
|
||||
<td width="15%"><input style="width: 200px; visibility:hidden" type="text" name="netpass" id="netpass" class="cbi-input-text" placeholder="password" onchange="return changeid()" ></input></td>
|
||||
<td width="15%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section" id="cbi-mod3" >
|
||||
<table width="100%" border="0" id="meshroam" >
|
||||
<tr>
|
||||
<td width="17%"><div align="left" id="roam1" style="font-size:1.5em"><strong>Access Point Roaming</strong></div></td>
|
||||
<td width="10%"></td>
|
||||
<td width="12%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="17%"><div align="right" id="enc1" style="font-size:1em"><strong>Enable Low Signal Roaming </strong></div></td>
|
||||
<td width="10%"><input type="checkbox" id="sigenb" onclick="return setlow(this)" /></td>
|
||||
<td width="12%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr id="roam11">
|
||||
<td width="17%"><div align="right" id="roam1" ><strong>Roaming ID </strong></div></td>
|
||||
<td width="10%" ><input style="width: 200px;" type="text" name="idsig" id="idsig" class="cbi-input-text" value="mesh" onchange="return changesigid()" ></input></td>
|
||||
<td width="12%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<table id="cmdtxt" width="700" border="0" style="display:table;">
|
||||
<tr>
|
||||
<td width="100%">
|
||||
<textarea readonly="readonly" name="attxt" id="attxt" rows="6" style="width: 600px;" maxlength="160"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
<%+footer%>
|
251
rooter/0mesh/mesh-mesh/files/usr/lib/mesh/checker.sh
Normal file
251
rooter/0mesh/mesh-mesh/files/usr/lib/mesh/checker.sh
Normal file
@ -0,0 +1,251 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
log() {
|
||||
logger -t "Checker" "$@"
|
||||
}
|
||||
|
||||
channel2="1,2,3,4,5,6,7,8,9,10,11,12,13,14"
|
||||
channel5="36,40,44,48,149,153,157,161,165,169"
|
||||
channel5dfs="36,40,44,48,52,56,60,64,100,104,104,112,116,132,136,140,144,149,153,157,161,165,169"
|
||||
|
||||
absolute() {
|
||||
num=$1
|
||||
if [ "$num" -lt 0 ]; then
|
||||
num=$((-num))
|
||||
fi
|
||||
}
|
||||
|
||||
loadconfig() {
|
||||
X=$(uci -q get wireless.wmesh.device)
|
||||
uci set mesh.radio.radionumber=$(echo ${X#radio})
|
||||
|
||||
uci set mesh.radio.dedicated=$(uci -q get wireless.default_$X.disabled)
|
||||
|
||||
chanwidth=$(uci -q get wireless.$X.htmode)
|
||||
case $chanwidth in
|
||||
"HT20" )
|
||||
chanwidth=0
|
||||
;;
|
||||
"HT40" )
|
||||
chanwidth=1
|
||||
;;
|
||||
"VHT80" )
|
||||
chanwidth=2
|
||||
;;
|
||||
"VHT160" )
|
||||
chanwidth=2
|
||||
;;
|
||||
esac
|
||||
uci set mesh.radio.channelwidth=$chanwidth
|
||||
|
||||
chan=$(uci -q get wireless.$X.channel)
|
||||
if [ $chan -lt 15 ]; then
|
||||
uci set mesh.radio.channellist=0
|
||||
uci set mesh.radio.channelindex=$((${chan}-1))
|
||||
else
|
||||
dfs=$(uci -q get wireless.$X.usedfs)
|
||||
if [ -z $dfs ]; then
|
||||
dfs=1
|
||||
uci set mesh.radio.usedfs=1
|
||||
else
|
||||
uci set mesh.radio.usedfs=$dfs
|
||||
fi
|
||||
if [ $dfs -eq 0 ]; then
|
||||
uci set mesh.radio.channellist=1
|
||||
clist=$channel5
|
||||
else
|
||||
uci set mesh.radio.channellist=2
|
||||
clist=$channel5dfs
|
||||
fi
|
||||
cindex=1
|
||||
while [ true ]
|
||||
do
|
||||
chan=$(echo "$clist" | cut -d, -f$cindex)
|
||||
if [ $chan -eq $channel ]; then
|
||||
uci set mesh.radio.channelindex=$((${cindex}-1))
|
||||
break
|
||||
fi
|
||||
cindex=$((${cindex}+1))
|
||||
done
|
||||
fi
|
||||
|
||||
enc=$(uci -q get wireless.wmesh.encryption)
|
||||
if [ $enc = "sae" ]; then
|
||||
uci set mesh.network.netencrypted=1
|
||||
uci set mesh.network.netpassword=$(uci -q get wireless.wmesh.key)
|
||||
else
|
||||
uci set mesh.network.netencrypted=0
|
||||
uci set mesh.network.netpassword="password"
|
||||
fi
|
||||
|
||||
uci set mesh.network.networkid=$(uci -q get wireless.wmesh.mesh_id)
|
||||
|
||||
snr=$(uci -q get wireless.default_$X.ieee80211r)
|
||||
if [ ! -z $snr ]; then
|
||||
uci set mesh.roam.signalenable=$snr
|
||||
uci set mesh.roam.signalid=$(uci -q get wireless.default_$X.mobility_domain)
|
||||
else
|
||||
uci set mesh.roam.signalenable=0
|
||||
uci set mesh.roam.signalid="abcd"
|
||||
fi
|
||||
|
||||
uci commit mesh
|
||||
}
|
||||
|
||||
count_radio() {
|
||||
local config=$1
|
||||
local channel
|
||||
|
||||
uci set wireless.default_radio$count.ieee80211r=$signalenable
|
||||
uci set wireless.default_radio$count.mobility_domain=$signalid
|
||||
uci set wireless.default_radio$count.ft_over_ds="1"
|
||||
uci set wireless.default_radio$count.ft_psk_generate_local="1"
|
||||
count=$((${count}+1))
|
||||
|
||||
}
|
||||
|
||||
loadmesh() {
|
||||
radionum=$(uci -q get mesh.radio.radionumber)
|
||||
dedicated=$(uci -q get mesh.radio.dedicated)
|
||||
if [ -z $dedicated ]; then
|
||||
dedicated="0"
|
||||
fi
|
||||
log "default_radio$radionum disabled = $dedicated"
|
||||
|
||||
chanwidth=$(uci -q get mesh.radio.channelwidth)
|
||||
case $chanwidth in
|
||||
"0" )
|
||||
chanwidth=20
|
||||
;;
|
||||
"1" )
|
||||
chanwidth=40
|
||||
;;
|
||||
"2" )
|
||||
chanwidth=80
|
||||
;;
|
||||
"3" )
|
||||
chanwidth=80
|
||||
;;
|
||||
esac
|
||||
cwidth=$(uci -q get wireless.radio$radionum.htmode)
|
||||
ht=$(echo "$cwidth" | grep "VHT")
|
||||
if [ ! -z $ht ]; then
|
||||
cwidth="VHT"$chanwidth
|
||||
else
|
||||
cwidth="HT"$chanwidth
|
||||
fi
|
||||
log "radio$radionum htmode = $cwidth"
|
||||
|
||||
clist=$(uci -q get mesh.radio.channellist)
|
||||
cindex=$(uci -q get mesh.radio.channelindex)
|
||||
cindex=$((${cindex}+1))
|
||||
case $clist in
|
||||
"0" )
|
||||
channel=$(echo "$channel2" | cut -d, -f$cindex)
|
||||
;;
|
||||
"1" )
|
||||
channel=$(echo "$channel5" | cut -d, -f$cindex)
|
||||
;;
|
||||
"2" )
|
||||
channel=$(echo "$channel5dfs" | cut -d, -f$cindex)
|
||||
;;
|
||||
esac
|
||||
log "radio$radionum channel = $channel"
|
||||
|
||||
networkid=$(uci -q get mesh.network.networkid)
|
||||
netencrypted=$(uci -q get mesh.network.netencrypted)
|
||||
netpassword=$(uci -q get mesh.network.netpassword)
|
||||
log "mesh_id = $networkid"
|
||||
log "encryption = $netencrypted key = $netpassword"
|
||||
|
||||
signalenable=$(uci -q get mesh.roam.signalenable)
|
||||
signalid=$(uci -q get mesh.roam.signalid)
|
||||
log "roam enable = $signalenable"
|
||||
log "id = $signalid"
|
||||
|
||||
ipaddr=$(uci -q get network.lan.ipaddr)
|
||||
|
||||
uci set wireless.default_radio$radionum.disabled=$dedicated
|
||||
uci set wireless.radio$radionum.htmode=$cwidth
|
||||
uci set wireless.radio$radionum.channel=$channel
|
||||
|
||||
count=0
|
||||
config_load wireless
|
||||
config_foreach count_radio wifi-iface
|
||||
|
||||
uci set wireless.wmesh=wifi-iface
|
||||
uci set wireless.wmesh.device=radio$radionum
|
||||
uci set wireless.wmesh.network="mesh"
|
||||
uci set wireless.wmesh.ifname="if-mesh"
|
||||
uci set wireless.wmesh.mode="mesh"
|
||||
uci set wireless.wmesh.mesh_fwding="0"
|
||||
uci set wireless.wmesh.mesh_id=$networkid
|
||||
uci set wireless.w.encryption="none"
|
||||
if [ $netencrypted = "1" ]; then
|
||||
uci set wireless.wmesh.encryption="sae"
|
||||
uci set wireless.wmesh.key=$netpassword
|
||||
fi
|
||||
uci set wireless.wmesh.mesh_ttl='1'
|
||||
uci set wireless.wmesh.mcast_rate='24000'
|
||||
uci set wireless.wmesh.disabled='0'
|
||||
uci commit wireless
|
||||
|
||||
uci set alfred.alfred.batmanif='bat0'
|
||||
uci set alfred.alfred.disabled='0'
|
||||
uci commit alfred
|
||||
|
||||
uci set network.bat0=interface
|
||||
uci set network.bat0.proto='batadv'
|
||||
uci set network.bat0.routing_algo='BATMAN_IV'
|
||||
uci set network.bat0.aggregated_ogms='1'
|
||||
uci set network.bat0.ap_isolation='0'
|
||||
uci set network.bat0.bonding='0'
|
||||
uci set network.bat0.bridge_loop_avoidance='1'
|
||||
uci set network.bat0.distributed_arp_table='1'
|
||||
uci set network.bat0.fragmentation='1'
|
||||
uci set network.bat0.gw_mode='off'
|
||||
uci set network.bat0.hop_penalty='30'
|
||||
uci set network.bat0.isolation_mark='0x00000000/0x00000000'
|
||||
uci set network.bat0.log_level='0'
|
||||
uci set network.bat0.multicast_mode='1'
|
||||
uci set network.bat0.multicast_fanout='16'
|
||||
uci set network.bat0.network_coding='0'
|
||||
uci set network.bat0.orig_interval='1000'
|
||||
|
||||
uci set network.mesh=interface
|
||||
uci set network.mesh.proto='batadv_hardif'
|
||||
uci set network.mesh.master='bat0'
|
||||
uci set network.mesh.mtu='2304'
|
||||
uci set network.mesh.throughput_override='0'
|
||||
|
||||
uci set network.bat0_hardif_eth0=interface
|
||||
uci set network.bat0_hardif_eth0.proto='batadv_hardif'
|
||||
uci set network.bat0_hardif_eth0.master='bat0'
|
||||
uci set network.bat0_hardif_eth0.mtu='1536'
|
||||
uci set network.bat0_hardif_eth0.device='eth0'
|
||||
|
||||
uci set network.bat0_lan=interface
|
||||
uci set network.bat0_lan.proto='static'
|
||||
uci set network.bat0_lan.ipaddr=$ipaddr
|
||||
uci set network.bat0_lan.netmask='255.255.255.0'
|
||||
uci set network.bat0_lan.ip6assign='60'
|
||||
uci set network.bat0_lan.device='bat0'
|
||||
uci commit network
|
||||
}
|
||||
|
||||
cmd=$1
|
||||
if [ -z $cmd ]; then
|
||||
WW=$(uci get wireless.wmesh)
|
||||
if [ -z $WW ]; then
|
||||
loadmesh
|
||||
reboot -f
|
||||
else
|
||||
loadconfig
|
||||
/usr/lib/mesh/ping.sh &
|
||||
fi
|
||||
else
|
||||
loadmesh
|
||||
fi
|
||||
|
||||
return
|
34
rooter/0mesh/mesh-mesh/files/usr/lib/mesh/ping.sh
Normal file
34
rooter/0mesh/mesh-mesh/files/usr/lib/mesh/ping.sh
Normal file
@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
pinging() {
|
||||
PING=0
|
||||
RETURN_CODE_1=$(curl -m 10 -s -o /dev/null -w "%{http_code}" http://www.google.com/)
|
||||
RETURN_CODE_2=$(curl -m 10 -s -o /dev/null -w "%{http_code}" http://www.example.org/)
|
||||
RETURN_CODE_3=$(curl -m 10 -s -o /dev/null -w "%{http_code}" https://github.com)
|
||||
|
||||
if [[ "$RETURN_CODE_1" != "200" && "$RETURN_CODE_2" != "200" && "$RETURN_CODE_3" != "200" ]]; then
|
||||
PING=1
|
||||
fi
|
||||
}
|
||||
|
||||
gateway() {
|
||||
mode=$1
|
||||
# batman-adv gateway handling (DHCP mangling)
|
||||
[ "$(uci -q get batman-adv.bat0.gw_mode)" == "client" ] || return
|
||||
if grep -q "^=>" /sys/kernel/debug/batman_adv/bat0/gateways ; then
|
||||
BATTYPE=gw BATACTION=$mode /etc/hotplug.d/net/99-batman-gw
|
||||
fi
|
||||
}
|
||||
|
||||
while true ; do
|
||||
sleep 20
|
||||
pinging
|
||||
if [ $PING -eq 1 ]; then
|
||||
gateway add
|
||||
batctl gw_mode client
|
||||
else
|
||||
gateway del
|
||||
batctl gw_mode server 10000
|
||||
fi
|
||||
done
|
78
rooter/0mesh/mesh-mesh/files/usr/lib/mesh/radio.sh
Normal file
78
rooter/0mesh/mesh-mesh/files/usr/lib/mesh/radio.sh
Normal file
@ -0,0 +1,78 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
log() {
|
||||
logger -t "Radio" "$@"
|
||||
}
|
||||
|
||||
count_radio() {
|
||||
local config=$1
|
||||
local channel
|
||||
|
||||
config_get channel $1 channel
|
||||
count=$((${count}+1))
|
||||
}
|
||||
|
||||
do_radio() {
|
||||
local config=$1
|
||||
local channel
|
||||
|
||||
config_get channel $1 channel
|
||||
rn=${config#radio}
|
||||
freq="1"
|
||||
if [ $channel -lt 15 ]; then
|
||||
freq="0"
|
||||
fi
|
||||
iwin=$(iw phy phy$rn info)
|
||||
hw=0
|
||||
hwt=$(echo "$iwin" | grep 'short GI for 40 MHz')
|
||||
if [ ! -z "$hwt" ]; then
|
||||
hw=1
|
||||
fi
|
||||
hwt=$(echo "$iwin" | grep 'short GI (80 MHz)')
|
||||
if [ ! -z "$hwt" ]; then
|
||||
hw=2
|
||||
fi
|
||||
hwt=$(echo "$iwin" | grep 'short GI (160')
|
||||
if [ ! -z "$hwt" ]; then
|
||||
hw=3
|
||||
fi
|
||||
echo "$freq|$rn|$hw" >> /tmp/radiolist
|
||||
}
|
||||
|
||||
count=0
|
||||
rm -f /tmp/radiolist
|
||||
config_load wireless
|
||||
config_foreach count_radio wifi-device
|
||||
if [ $count -gt 0 ]; then
|
||||
echo "$count" > /tmp/radiolist
|
||||
config_foreach do_radio wifi-device
|
||||
fi
|
||||
|
||||
CF1=$(uci -q get mesh.radio.radionumber)
|
||||
CF2=$(uci -q get mesh.radio.channelindex)
|
||||
CF3=$(uci -q get mesh.radio.channellist)
|
||||
CF4=$(uci -q get mesh.radio.channelwidth)
|
||||
CF5=$(uci -q get mesh.radio.usedfs)
|
||||
CF6=$(uci -q get mesh.radio.dedicated)
|
||||
echo "$CF1" >> /tmp/radiolist
|
||||
echo "$CF2" >> /tmp/radiolist
|
||||
echo "$CF3" >> /tmp/radiolist
|
||||
echo "$CF4" >> /tmp/radiolist
|
||||
echo "$CF5" >> /tmp/radiolist
|
||||
echo "$CF6" >> /tmp/radiolist
|
||||
|
||||
CF1=$(uci -q get mesh.network.networkid)
|
||||
CF2=$(uci -q get mesh.network.netencrypted)
|
||||
CF3=$(uci -q get mesh.network.netpassword)
|
||||
echo "$CF1" >> /tmp/radiolist
|
||||
echo "$CF2" >> /tmp/radiolist
|
||||
echo "$CF3" >> /tmp/radiolist
|
||||
|
||||
CF1=$(uci -q get mesh.roam.signalenable)
|
||||
CF2=$(uci -q get mesh.roam.signalid)
|
||||
echo "$CF1" >> /tmp/radiolist
|
||||
echo "$CF2" >> /tmp/radiolist
|
||||
|
||||
|
||||
|
25
rooter/0mesh/mesh-mesh/files/usr/lib/mesh/save.sh
Normal file
25
rooter/0mesh/mesh-mesh/files/usr/lib/mesh/save.sh
Normal file
@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
log() {
|
||||
logger -t "Save" "$@"
|
||||
}
|
||||
|
||||
state=$1
|
||||
|
||||
state=$(echo "$state" | tr "|" ",")
|
||||
uci set mesh.radio.radionumber=$(echo "$state" | cut -d, -f1)
|
||||
uci set mesh.radio.channelindex=$(echo "$state" | cut -d, -f2)
|
||||
uci set mesh.radio.channellist=$(echo "$state" | cut -d, -f3)
|
||||
uci set mesh.radio.usedfs=$(echo "$state" | cut -d, -f4)
|
||||
uci set mesh.radio.channelwidth=$(echo "$state" | cut -d, -f5)
|
||||
uci set mesh.radio.dedicated=$(echo "$state" | cut -d, -f6)
|
||||
|
||||
uci set mesh.network.networkid=$(echo "$state" | cut -d, -f7)
|
||||
uci set mesh.network.netencrypted=$(echo "$state" | cut -d, -f8)
|
||||
uci set mesh.network.netpassword=$(echo "$state" | cut -d, -f9)
|
||||
|
||||
uci set mesh.roam.signalenable=$(echo "$state" | cut -d, -f10)
|
||||
uci set mesh.roam.signalid=$(echo "$state" | cut -d, -f11)
|
||||
|
||||
uci commit mesh
|
16
rooter/0mesh/mesh-mesh/files/usr/lib/mesh/savecfg.sh
Normal file
16
rooter/0mesh/mesh-mesh/files/usr/lib/mesh/savecfg.sh
Normal file
@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
log() {
|
||||
logger -t "Save" "$@"
|
||||
}
|
||||
|
||||
state=$1
|
||||
|
||||
PKI_DIR="/www"
|
||||
cd ${PKI_DIR}
|
||||
mkdir -p package
|
||||
cd ..
|
||||
chmod -R 0777 ${PKI_DIR}/package
|
||||
|
||||
echo "$state" > ${PKI_DIR}/package/meshcfg.meshcfg
|
8
rooter/0mesh/mesh-mesh/files/usr/lib/mesh/startstop.sh
Normal file
8
rooter/0mesh/mesh-mesh/files/usr/lib/mesh/startstop.sh
Normal file
@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
log() {
|
||||
logger -t "Start Mesh" "$@"
|
||||
}
|
||||
|
||||
/usr/lib/mesh/checker.sh 1
|
@ -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].x<j[n].x)&&(2!=m&&7!=n||j[m].x>j[n].x)&&(0!=m&&5!=n||j[m].y>j[n].y)&&(1!=m&&4!=n||j[m].y<j[n].y))&&(l.push(o+p),k[l[l.length-1].toFixed(3)]=[m,n])}var q=0==l.length?[0,4]:k[Math.min.apply(Math,l).toFixed(3)],r=j[q[0]].x,s=j[q[0]].y,t=j[q[1]].x,u=j[q[1]].y,o=Math.max(Math.abs(r-t)/2,10),p=Math.max(Math.abs(s-u)/2,10),v=[r,r,r-o,r+o][q[0]].toFixed(3),w=[s-p,s+p,s,s][q[0]].toFixed(3),x=[0,0,0,0,t,t,t-o,t+o][q[1]].toFixed(3),y=[0,0,0,0,s+p,s-p,u,u][q[1]].toFixed(3),z=["M",r.toFixed(3),s.toFixed(3),"C",v,w,x,y,t.toFixed(3),u.toFixed(3)].join(",");if(c&&c.directed){var A=Math.sqrt((u-y)*(u-y)+(t-x)*(t-x)),B=function(a,b){return-a*(b||5)/A},C=[{x:(B(t-x)+B(u-y)+t).toFixed(3),y:(B(u-y)+B(t-x)+u).toFixed(3)},{x:(B(t-x)-B(u-y)+t).toFixed(3),y:(B(u-y)-B(t-x)+u).toFixed(3)}];z=z+",M"+C[0].x+","+C[0].y+",L"+t+","+u+",L"+C[1].x+","+C[1].y}var D="attr";e.fg&&e.fg[D]({path:z})||(e.fg=d.path(z).attr({stroke:c&&c.stroke||"#000",fill:"none"}).toBack()),e.bg&&e.bg[D]({path:z})||c&&c.fill&&(e.bg=c.fill.split&&d.path(z).attr({stroke:c.fill.split("|")[0],fill:"none","stroke-width":c.fill.split("|")[1]||3}).toBack()),c&&c.label&&(e.label&&e.label.attr({x:(r+t)/2,y:(s+u)/2})||(e.label=d.text((r+t)/2,(s+u)/2,c.label).attr({fill:"#000","font-size":c["font-size"]||"12px"}))),c&&c.label&&c["label-style"]&&e.label&&e.label.attr(c["label-style"]),c&&c.callback&&c.callback(e)}};return e.draw(),e};
|
File diff suppressed because one or more lines are too long
7
rooter/0mesh/mesh-mesh/files/www/luci-static/resources/dracula/raphael-min.js
vendored
Normal file
7
rooter/0mesh/mesh-mesh/files/www/luci-static/resources/dracula/raphael-min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
154
rooter/0mesh/mesh-mesh/files/www/luci-static/resources/jquery/jquery-1.4.js
vendored
Normal file
154
rooter/0mesh/mesh-mesh/files/www/luci-static/resources/jquery/jquery-1.4.js
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
/*!
|
||||
* 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<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
|
||||
e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
|
||||
j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
|
||||
"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
|
||||
true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\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<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
|
||||
c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
|
||||
L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
|
||||
"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
|
||||
a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
|
||||
d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
|
||||
a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
|
||||
!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
|
||||
true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
|
||||
var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
|
||||
parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
|
||||
false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
|
||||
s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
|
||||
applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
|
||||
else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
|
||||
a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
|
||||
w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
|
||||
cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
|
||||
i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
|
||||
" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
|
||||
this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
|
||||
e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
|
||||
c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
|
||||
a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
|
||||
function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
|
||||
k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
|
||||
C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
|
||||
null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
|
||||
e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
|
||||
f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
|
||||
if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
|
||||
fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
|
||||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
|
||||
"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
|
||||
a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
|
||||
isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
|
||||
{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
|
||||
if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
|
||||
e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
|
||||
"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
|
||||
d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
|
||||
!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
|
||||
toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
|
||||
u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
|
||||
function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
|
||||
if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
|
||||
e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
|
||||
t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
|
||||
g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
|
||||
for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
|
||||
1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
|
||||
CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
|
||||
relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
|
||||
l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
|
||||
h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
|
||||
CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
|
||||
g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
|
||||
text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
|
||||
setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
|
||||
h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
|
||||
m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
|
||||
"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
|
||||
h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
|
||||
!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
|
||||
h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
|
||||
q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
|
||||
if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
|
||||
(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
|
||||
function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
|
||||
gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
|
||||
c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
|
||||
{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
|
||||
"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
|
||||
d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
|
||||
a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
|
||||
1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
|
||||
a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
|
||||
c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
|
||||
wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
|
||||
prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
|
||||
this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
|
||||
return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
|
||||
""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
|
||||
this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
|
||||
u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
|
||||
1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
|
||||
return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
|
||||
""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
|
||||
c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
|
||||
c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
|
||||
function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
|
||||
Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
|
||||
"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
|
||||
a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
|
||||
a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
|
||||
"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
|
||||
serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
|
||||
function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
|
||||
global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
|
||||
e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
|
||||
"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
|
||||
false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
|
||||
false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
|
||||
c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
|
||||
d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
|
||||
g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
|
||||
1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
|
||||
"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
|
||||
if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
|
||||
this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
|
||||
"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
|
||||
animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
|
||||
j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
|
||||
this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
|
||||
"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
|
||||
c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
|
||||
this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
|
||||
this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
|
||||
e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
|
||||
c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
|
||||
function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
|
||||
this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
|
||||
k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
|
||||
f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
|
||||
a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
|
||||
c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
|
||||
d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
|
||||
f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
|
||||
"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
|
||||
e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
|
@ -0,0 +1,8 @@
|
||||
'use strict';
|
||||
'require network';
|
||||
|
||||
return network.registerProtocol('batadv', {
|
||||
getI18n: function() {
|
||||
return _('Batman');
|
||||
}
|
||||
});
|
@ -0,0 +1,8 @@
|
||||
'use strict';
|
||||
'require network';
|
||||
|
||||
return network.registerProtocol('batadv_hardif', {
|
||||
getI18n: function() {
|
||||
return _('Mesh');
|
||||
}
|
||||
});
|
29
rooter/0mesh/mesh-wpad/Makefile
Normal file
29
rooter/0mesh/mesh-wpad/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
#Owned by DairyMan@Whirlpool
|
||||
#
|
||||
#Copyright GNU act.
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=mesh-wpad
|
||||
PKG_VERSION:=1.000
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/mesh-wpad
|
||||
SECTION:=utils
|
||||
CATEGORY:=ROOter
|
||||
SUBMENU:=Mesh Support
|
||||
DEPENDS:=+wpad-mesh-openssl
|
||||
TITLE:=Support for Mesh routing
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/mesh-wpad/description
|
||||
Helper scripts to install Meshing
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,mesh-wpad))
|
34
rooter/0optionalapps/bwallocate/Makefile
Normal file
34
rooter/0optionalapps/bwallocate/Makefile
Normal file
@ -0,0 +1,34 @@
|
||||
#Owned by DairyMan@Whirlpool
|
||||
#
|
||||
#Copyright GNU act.
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=bwallocate
|
||||
PKG_VERSION:=4.500
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/bwallocate
|
||||
SECTION:=utils
|
||||
CATEGORY:=ROOter
|
||||
SUBMENU:=Optional Applications
|
||||
DEPENDS:=+ext-throttle +msmtp
|
||||
TITLE:=Install scripts for Bandwidth Allocation
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/bwallocate/description
|
||||
Install scripts for Bandwidth Allocation
|
||||
endef
|
||||
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/bwallocate/install
|
||||
$(CP) ./files/* $(1)/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,bwallocate))
|
14
rooter/0optionalapps/bwallocate/files/etc/init.d/textbwint
Normal file
14
rooter/0optionalapps/bwallocate/files/etc/init.d/textbwint
Normal file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=88
|
||||
|
||||
log() {
|
||||
logger -t "TEXTING" "$@"
|
||||
}
|
||||
|
||||
start()
|
||||
{
|
||||
uci set bwmon.general.enabled="1"
|
||||
uci commit bwmon
|
||||
/usr/lib/bwmon/textbw.sh &
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
module("luci.controller.bwallocate", package.seeall)
|
||||
|
||||
I18N = require "luci.i18n"
|
||||
translate = I18N.translate
|
||||
|
||||
function index()
|
||||
local lock = luci.model.uci.cursor():get("custom", "menu", "full")
|
||||
local multilock = luci.model.uci.cursor():get("custom", "multiuser", "multi") or "0"
|
||||
local rootlock = luci.model.uci.cursor():get("custom", "multiuser", "root") or "0"
|
||||
if (multilock == "0") or (multilock == "1" and rootlock == "1") then
|
||||
if lock == "1" then
|
||||
local lock1 = luci.model.uci.cursor():get("custom", "bwallocate", "lock")
|
||||
if lock1 == "1" then
|
||||
if (multilock == "1" and rootlock == "1") then
|
||||
entry({"admin", "adminmenu", "bwmenu"}, cbi("fullmenu/bwmenu"), translate("Bandwidth Allocation"), 6)
|
||||
else
|
||||
entry({"admin", "adminmenu", "bwmenu"}, cbi("fullmenu/bwmenu"), translate("---Bandwidth Allocation"), 6)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,267 @@
|
||||
local utl = require "luci.util"
|
||||
|
||||
m = Map("custom", translate("Bandwidth Allocation"), translate("Set Maximum Bandwidth Usage before Internet blockage"))
|
||||
|
||||
m.on_after_save = function(self)
|
||||
luci.sys.call("/usr/lib/bwmon/allocate.sh 0 &")
|
||||
end
|
||||
|
||||
s = m:section(TypedSection, "bwallocate", translate("Allocation Settings"))
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
s:option(Flag, "enabled", translate("Allocation Enabled : "))
|
||||
|
||||
maxim = s:option(Value, "allocate", translate("Maximum Bandwidth in GB : "), translate("Maximum amount of bandwidth that can be used before Internet is affected"));
|
||||
maxim.rmempty = true;
|
||||
maxim.optional=false;
|
||||
maxim.default="1000";
|
||||
maxim.datatype = "and(uinteger,min(1))"
|
||||
|
||||
rollover = s:option(ListValue, "rollover", translate("Rollover Day : "), translate("Day of the month when bandwidth usage resets"))
|
||||
rollover.rmempty = true
|
||||
rollover:value("1", "1st")
|
||||
rollover:value("2", "2nd")
|
||||
rollover:value("3", "3rd")
|
||||
rollover:value("4", "4th")
|
||||
rollover:value("5", "5th")
|
||||
rollover:value("6", "6th")
|
||||
rollover:value("7", "7th")
|
||||
rollover:value("8", "8th")
|
||||
rollover:value("9", "9th")
|
||||
rollover:value("10", "10th")
|
||||
rollover:value("11", "11th")
|
||||
rollover:value("12", "12th")
|
||||
rollover:value("13", "13th")
|
||||
rollover:value("14", "14th")
|
||||
rollover:value("15", "15th")
|
||||
rollover:value("16", "16th")
|
||||
rollover:value("17", "17th")
|
||||
rollover:value("18", "18th")
|
||||
rollover:value("19", "19th")
|
||||
rollover:value("20", "20th")
|
||||
rollover:value("21", "21th")
|
||||
rollover:value("22", "22th")
|
||||
rollover:value("23", "23th")
|
||||
rollover:value("24", "24th")
|
||||
rollover:value("25", "25th")
|
||||
rollover:value("26", "26th")
|
||||
rollover:value("27", "27th")
|
||||
rollover:value("28", "28th")
|
||||
rollover.default = "1"
|
||||
|
||||
act = s:option(ListValue, "action", translate("Internet Action : "), translate("Action taken when allocation is exceeded"))
|
||||
act.rmempty = true
|
||||
act:value("0", "Internet Blocked")
|
||||
act:value("1", "Internet Throttled")
|
||||
act.default = "0"
|
||||
|
||||
down = s:option(Value, "down", translate("Download Speed in Mbps :"));
|
||||
down.optional=false;
|
||||
down.rmempty = true;
|
||||
down.datatype = "and(uinteger,min(1),max(999))"
|
||||
down:depends("action", "1")
|
||||
down.default = "5"
|
||||
|
||||
up = s:option(Value, "up", translate("Upload Speed in Mbps :"));
|
||||
up.optional=false;
|
||||
up.rmempty = true;
|
||||
up.datatype = "and(uinteger,min(1),max(999))"
|
||||
up:depends("action", "1")
|
||||
up.default = "2"
|
||||
|
||||
s = m:section(TypedSection, "texting", translate("Text/Email Settings"))
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
aact = s:option(ListValue, "text", translate("Enable : "), translate("Enable Sending Text or Email Information"))
|
||||
aact.rmempty = true
|
||||
aact:value("0", "No")
|
||||
aact:value("1", "Yes")
|
||||
aact.default = "0"
|
||||
|
||||
|
||||
pph = s:option(Value, "ident", translate("Identifier :"));
|
||||
pph.optional=false;
|
||||
pph.rmempty = true;
|
||||
pph:depends("text", "1")
|
||||
pph.default = "xxx"
|
||||
|
||||
|
||||
|
||||
ct = s:option(ListValue, "method", translate("Criteria : "), translate("Criteria used to determine when to send information"))
|
||||
ct.rmempty = true
|
||||
ct:value("0", translate("By Specified Time Interval"))
|
||||
ct:value("1", translate("By Amount Used"))
|
||||
ct:value("2", translate("By Percentage Used"))
|
||||
ct.default = "0"
|
||||
ct:depends("text", "1")
|
||||
|
||||
sdhour = s:option(ListValue, "time", translate("Sending Time :"), translate("Time to send information"))
|
||||
sdhour.rmempty = true
|
||||
sdhour:value("0", "12:00 AM")
|
||||
sdhour:value("1", "12:15 AM")
|
||||
sdhour:value("2", "12:30 AM")
|
||||
sdhour:value("3", "12:45 AM")
|
||||
sdhour:value("4", "01:00 AM")
|
||||
sdhour:value("5", "01:15 AM")
|
||||
sdhour:value("6", "01:30 AM")
|
||||
sdhour:value("7", "01:45 AM")
|
||||
sdhour:value("8", "02:00 AM")
|
||||
sdhour:value("9", "02:15 AM")
|
||||
sdhour:value("10", "02:30 AM")
|
||||
sdhour:value("11", "02:45 AM")
|
||||
sdhour:value("12", "03:00 AM")
|
||||
sdhour:value("13", "03:15 AM")
|
||||
sdhour:value("14", "03:30 AM")
|
||||
sdhour:value("15", "03:45 AM")
|
||||
sdhour:value("16", "04:00 AM")
|
||||
sdhour:value("17", "04:15 AM")
|
||||
sdhour:value("18", "04:30 AM")
|
||||
sdhour:value("19", "04:45 AM")
|
||||
sdhour:value("20", "05:00 AM")
|
||||
sdhour:value("21", "05:15 AM")
|
||||
sdhour:value("22", "05:30 AM")
|
||||
sdhour:value("23", "05:45 AM")
|
||||
sdhour:value("24", "06:00 AM")
|
||||
sdhour:value("25", "06:15 AM")
|
||||
sdhour:value("26", "06:30 AM")
|
||||
sdhour:value("27", "06:45 AM")
|
||||
sdhour:value("28", "07:00 AM")
|
||||
sdhour:value("29", "07:15 AM")
|
||||
sdhour:value("30", "07:30 AM")
|
||||
sdhour:value("31", "07:45 AM")
|
||||
sdhour:value("32", "08:00 AM")
|
||||
sdhour:value("33", "08:15 AM")
|
||||
sdhour:value("34", "08:30 AM")
|
||||
sdhour:value("35", "08:45 AM")
|
||||
sdhour:value("36", "09:00 AM")
|
||||
sdhour:value("37", "09:15 AM")
|
||||
sdhour:value("38", "09:30 AM")
|
||||
sdhour:value("39", "09:45 AM")
|
||||
sdhour:value("40", "10:00 AM")
|
||||
sdhour:value("41", "10:15 AM")
|
||||
sdhour:value("42", "10:30 AM")
|
||||
sdhour:value("43", "10:45 AM")
|
||||
sdhour:value("44", "11:00 AM")
|
||||
sdhour:value("45", "11:15 AM")
|
||||
sdhour:value("46", "11:30 AM")
|
||||
sdhour:value("47", "11:45 AM")
|
||||
sdhour:value("48", "12:00 PM")
|
||||
sdhour:value("49", "12:15 PM")
|
||||
sdhour:value("50", "12:30 PM")
|
||||
sdhour:value("51", "12:45 PM")
|
||||
sdhour:value("52", "01:00 PM")
|
||||
sdhour:value("53", "01:15 PM")
|
||||
sdhour:value("54", "01:30 PM")
|
||||
sdhour:value("55", "01:45 PM")
|
||||
sdhour:value("56", "02:00 PM")
|
||||
sdhour:value("57", "02:15 PM")
|
||||
sdhour:value("58", "02:30 PM")
|
||||
sdhour:value("59", "02:45 PM")
|
||||
sdhour:value("60", "03:00 PM")
|
||||
sdhour:value("61", "03:15 PM")
|
||||
sdhour:value("62", "03:30 PM")
|
||||
sdhour:value("63", "03:45 PM")
|
||||
sdhour:value("64", "04:00 PM")
|
||||
sdhour:value("65", "04:15 PM")
|
||||
sdhour:value("66", "04:30 PM")
|
||||
sdhour:value("67", "04:45 PM")
|
||||
sdhour:value("68", "05:00 PM")
|
||||
sdhour:value("69", "05:15 PM")
|
||||
sdhour:value("70", "05:30 PM")
|
||||
sdhour:value("71", "05:45 PM")
|
||||
sdhour:value("72", "06:00 PM")
|
||||
sdhour:value("73", "06:15 PM")
|
||||
sdhour:value("74", "06:30 PM")
|
||||
sdhour:value("75", "06:45 PM")
|
||||
sdhour:value("76", "07:00 PM")
|
||||
sdhour:value("77", "07:15 PM")
|
||||
sdhour:value("78", "07:30 PM")
|
||||
sdhour:value("79", "07:45 PM")
|
||||
sdhour:value("80", "08:00 PM")
|
||||
sdhour:value("81", "08:15 PM")
|
||||
sdhour:value("82", "08:30 PM")
|
||||
sdhour:value("83", "08:45 PM")
|
||||
sdhour:value("84", "09:00 PM")
|
||||
sdhour:value("85", "09:15 PM")
|
||||
sdhour:value("86", "09:30 PM")
|
||||
sdhour:value("87", "09:45 PM")
|
||||
sdhour:value("88", "10:00 PM")
|
||||
sdhour:value("89", "10:15 PM")
|
||||
sdhour:value("90", "10:30 PM")
|
||||
sdhour:value("91", "10:45 PM")
|
||||
sdhour:value("92", "11:00 PM")
|
||||
sdhour:value("93", "11:15 PM")
|
||||
sdhour:value("94", "11:30 PM")
|
||||
sdhour:value("95", "11:45 PM")
|
||||
sdhour:depends("text", "1")
|
||||
sdhour.default = "48"
|
||||
|
||||
xct = s:option(ListValue, "days", translate("Interval : "), translate("Number of days between sending information"))
|
||||
xct.rmempty = true
|
||||
xct:value("1", translate("Every Day"))
|
||||
xct:value("2", translate("Every 2 Days"))
|
||||
xct:value("5", translate("Every 5 Days"))
|
||||
xct:value("10", translate("Every 10 Days"))
|
||||
xct:value("15", translate("Every 15 Days"))
|
||||
xct.default = "5"
|
||||
xct:depends("method", "0")
|
||||
|
||||
xxct = s:option(ListValue, "increment", translate("Increment : "), translate("Amount Used between sending information"))
|
||||
xxct.rmempty = true
|
||||
xxct:value("50", translate("Every 50 GB"))
|
||||
xxct:value("75", translate("Every 75 GB"))
|
||||
xxct:value("100", translate("Every 100 GB"))
|
||||
xxct.default = "50"
|
||||
xxct:depends("method", "1")
|
||||
|
||||
ph1 = s:option(ListValue, "percent", translate("Percentage Used :"));
|
||||
ph1.optional=false;
|
||||
ph1.rmempty = true;
|
||||
ph1:value("10", translate("10%"))
|
||||
ph1:value("20", translate("20%"))
|
||||
ph1:value("30", translate("30%"))
|
||||
ph1:value("40", translate("40%"))
|
||||
ph1:value("50", translate("50%"))
|
||||
ph1:value("60", translate("60%"))
|
||||
ph1:value("70", translate("70%"))
|
||||
ph1:value("80", translate("80%"))
|
||||
ph1:value("90", translate("90%"))
|
||||
ph1:depends("method", "2")
|
||||
ph1.default = "90"
|
||||
|
||||
--b3 = s:option(DummyValue, "blank", " ");
|
||||
|
||||
btn = s:option(Button, "_btn", translate(" "))
|
||||
btn.inputtitle = translate("Send Test of Text or Email")
|
||||
btn.inputstyle = "apply"
|
||||
btn:depends("text", "1")
|
||||
function btn.write()
|
||||
luci.sys.call("/usr/lib/bwmon/dotext.sh")
|
||||
end
|
||||
|
||||
b4 = s:option(DummyValue, "blank", " ");
|
||||
|
||||
ct = s:option(ListValue, "tore", translate("Sending Method : "), translate("Method used to send information"))
|
||||
ct.rmempty = true
|
||||
ct:value("0", translate("By Text"))
|
||||
ct:value("1", translate("By Email"))
|
||||
ct.default = "0"
|
||||
ct:depends("text", "1")
|
||||
|
||||
ph = s:option(Value, "phone", translate("Phone Number :"));
|
||||
ph.optional=false;
|
||||
ph.rmempty = true;
|
||||
ph.datatype = "phonedigit"
|
||||
ph:depends("tore", "0")
|
||||
ph.default = "12223334444"
|
||||
|
||||
ph1 = s:option(Value, "email", translate("Email Address :"));
|
||||
ph1.optional=false;
|
||||
ph1.rmempty = true;
|
||||
ph1:depends("tore", "1")
|
||||
ph1.default = "jdoe@domain.com"
|
||||
|
||||
|
||||
return m
|
35
rooter/0optionalapps/bwmon/Makefile
Normal file
35
rooter/0optionalapps/bwmon/Makefile
Normal file
@ -0,0 +1,35 @@
|
||||
#Owned by DairyMan@Whirlpool
|
||||
#
|
||||
#Copyright GNU act.
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=bwmon
|
||||
PKG_VERSION:=1.000
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/bwmon
|
||||
SECTION:=utils
|
||||
CATEGORY:=ROOter
|
||||
SUBMENU:=Optional Applications
|
||||
TITLE:=Install Bandwidth Monitor
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/bwmon/description
|
||||
Helper scripts to install Bandwidth Monitor on ROOter
|
||||
endef
|
||||
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/bwmon/install
|
||||
$(CP) ./files/* $(1)/
|
||||
|
||||
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,bwmon))
|
9
rooter/0optionalapps/bwmon/files/etc/config/bwmon
Normal file
9
rooter/0optionalapps/bwmon/files/etc/config/bwmon
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
config general 'general'
|
||||
option external '0'
|
||||
option backup '30'
|
||||
option enabled '1'
|
||||
|
||||
|
||||
config bwwan 'bwwan'
|
||||
option wan '0'
|
18
rooter/0optionalapps/bwmon/files/etc/init.d/bwmon
Normal file
18
rooter/0optionalapps/bwmon/files/etc/init.d/bwmon
Normal file
@ -0,0 +1,18 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2006 OpenWrt.org
|
||||
|
||||
START=60
|
||||
|
||||
start() {
|
||||
WX=$(uci -q get custom.bwallocate.lock)
|
||||
if [ "$WX" = "1" ]; then
|
||||
uci set bwmon.general.enabled=$enable
|
||||
uci commit bwmon
|
||||
fi
|
||||
/usr/lib/bwmon/wrtbwmon.sh &
|
||||
/usr/lib/bwmon/create.sh &
|
||||
}
|
||||
|
||||
stop() {
|
||||
rmdir -f /tmp/WRTbmon
|
||||
}
|
@ -0,0 +1 @@
|
||||
/usr/lib/bwmon/data/
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user