summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSteven Barth <steven@midlink.org>2008-04-26 21:29:14 +0000
committerSteven Barth <steven@midlink.org>2008-04-26 21:29:14 +0000
commitf801df7d4d44d8b85ae17fa5d191b96602c1fa9a (patch)
treeb32af471a440d417837e640450dccda016434d2c
parent035a193353b9ad86621b6b1fa183ccb1e0bd9e3d (diff)
* luci-splash: Fixes
-rw-r--r--contrib/package/ffluci/Makefile5
-rw-r--r--contrib/package/luci-splash/Makefile12
-rw-r--r--contrib/package/luci-splash/src/luci-splash/htdocs/cgi-bin/index.cgi31
-rw-r--r--contrib/package/luci-splash/src/luci-splash/htdocs/index.html (renamed from contrib/package/luci-splash/src/luci_splash/htdocs/index.html)0
-rw-r--r--contrib/package/luci-splash/src/luci-splash/splash.lua93
-rw-r--r--contrib/package/luci-splash/src/luci-splash/sync.lua39
-rw-r--r--contrib/package/luci-splash/src/luci_splash.cron1
-rw-r--r--contrib/package/luci-splash/src/luci_splash.init17
-rw-r--r--contrib/package/luci-splash/src/luci_splash.uci10
-rw-r--r--contrib/package/luci-splash/src/luci_splash/htdocs/cgi-bin/index.cgi49
-rw-r--r--contrib/package/luci-splash/src/luci_splash/splash.lua74
-rw-r--r--contrib/package/luci-splash/src/luci_splash/sync.lua3
-rw-r--r--contrib/package/luci-splash/src/luci_splash_httpd.conf2
-rw-r--r--core/contrib/uci/luci1
-rw-r--r--core/src/ffluci/init.lua2
-rw-r--r--module/admin-core/contrib/luci-splash4
-rw-r--r--module/admin-core/src/model/cbi/admin_services/splash.lua (renamed from module/admin-core/src/model/cbi/admin_network/splash.lua)3
-rw-r--r--module/admin-core/src/model/menu/00admin.lua8
-rw-r--r--module/admin-core/src/view/admin_system/reboot.htm2
19 files changed, 199 insertions, 157 deletions
diff --git a/contrib/package/ffluci/Makefile b/contrib/package/ffluci/Makefile
index 62fe0657af..aa6050dab4 100644
--- a/contrib/package/ffluci/Makefile
+++ b/contrib/package/ffluci/Makefile
@@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=ffluci
PKG_REV:=HEAD
-PKG_VERSION:=0.2+svn$(PKG_REV)
+PKG_VERSION:=0.3+svn$(PKG_REV)
PKG_RELEASE:=1
PKG_BRANCH:=trunk
@@ -50,7 +50,7 @@ define Package/ffluci/install
$(CP) $(PKG_BUILD_DIR)/core/dist/* $(1)/usr/lib/lua/ -R
$(CP) $(PKG_BUILD_DIR)/core/contrib/uci/* $(1)/etc/config/
- $(CP) $(PKG_BUILD_DIR)/core/contrib/hotplug.d-20-aliases $(1)/etc/hotplug.d/iface -R
+ $(CP) $(PKG_BUILD_DIR)/core/contrib/hotplug.d-20-aliases $(1)/etc/hotplug.d/iface/20-aliases -R
$(INSTALL_BIN) $(PKG_BUILD_DIR)/core/contrib/ffluci $(1)/www/cgi-bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/core/contrib/ffluci-upload $(1)/www/cgi-bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/core/contrib/index.cgi $(1)/www/cgi-bin
@@ -62,6 +62,7 @@ define Package/ffluci/install
$(CP) $(PKG_BUILD_DIR)/module/admin-core/contrib/uci/luci_fw $(1)/etc/config/luci_fw
$(INSTALL_BIN) $(PKG_BUILD_DIR)/module/admin-core/contrib/init.d/luci_fw $(1)/etc/init.d/luci_fw
$(INSTALL_BIN) $(PKG_BUILD_DIR)/module/admin-core/contrib/ffluci-flash $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/module/admin-core/contrib/luci-splash $(1)/www/cgi-bin
$(CP) $(PKG_BUILD_DIR)/module/public-core/dist/* $(1)/usr/lib/lua/ffluci/ -R
$(CP) $(PKG_BUILD_DIR)/module/public-core/contrib/media $(1)/www/ffluci/ -R
diff --git a/contrib/package/luci-splash/Makefile b/contrib/package/luci-splash/Makefile
index eb41fde5dc..85cb5533fd 100644
--- a/contrib/package/luci-splash/Makefile
+++ b/contrib/package/luci-splash/Makefile
@@ -21,15 +21,17 @@ define Build/Compile
endef
define Package/luci-splash/install
- $(INSTALL_DIR) $(1)/usr/lib/luci_splash/htdocs
+ $(INSTALL_DIR) $(1)/usr/lib/luci-splash/htdocs
$(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DIR) $(1)/etc/crontabs
$(INSTALL_DIR) $(1)/etc/init.d
- $(CP) -a ./src/luci_splash/* $(1)/usr/lib/luci_splash/ -R
- $(INSTALL_BIN) ./src/luci_splash/sync.lua $(1)/usr/lib/luci_splash
- $(INSTALL_BIN) ./src/luci_splash/htdocs/cgi-bin/index.cgi $(1)/usr/lib/luci_splash/htdocs/cgi-bin
+ $(CP) -a ./src/luci-splash/* $(1)/usr/lib/luci-splash/ -R
+ $(INSTALL_BIN) ./src/luci-splash/sync.lua $(1)/usr/lib/luci-splash
+ $(INSTALL_BIN) ./src/luci-splash/htdocs/cgi-bin/index.cgi $(1)/usr/lib/luci-splash/htdocs/cgi-bin
+ $(INSTALL_BIN) ./src/luci_splash.init $(1)/etc/init.d/luci_splash
- $(CP) -a ./src/luci_splash.init $(1)/etc/init.d/luci_splash
+ $(CP) -a ./src/luci_splash.cron $(1)/etc/crontabs/luci_splash
$(CP) -a ./src/luci_splash.uci $(1)/etc/config/luci_splash
$(CP) -a ./src/luci_splash_httpd.conf $(1)/etc/
diff --git a/contrib/package/luci-splash/src/luci-splash/htdocs/cgi-bin/index.cgi b/contrib/package/luci-splash/src/luci-splash/htdocs/cgi-bin/index.cgi
new file mode 100644
index 0000000000..88f67c2acc
--- /dev/null
+++ b/contrib/package/luci-splash/src/luci-splash/htdocs/cgi-bin/index.cgi
@@ -0,0 +1,31 @@
+#!/usr/bin/haserl --shell=luac
+dofile("/usr/lib/luci-splash/splash.lua")
+
+local srv
+local ip = ffluci.http.remote_addr()
+for k, v in pairs(uci:show("network").network) do
+ if v[".type"] == "interface" then
+ local p = ffluci.sys.net.mask4prefix(v.netmask)
+ if ffluci.sys.net.belongs(ip, v.ipaddr, p) then
+ srv = v.ipaddr
+ end
+ end
+end
+
+if not srv then
+ ffluci.http.textheader()
+ return print("Unable to detect network settings!")
+end
+
+local action = "splash"
+
+local mac = ip4mac(ip)
+if not mac then
+ action = "unknown"
+end
+
+if iswhitelisted(mac) or haslease(mac) then
+ action = "allowed"
+end
+
+ffluci.http.redirect("http://" .. srv .. "/cgi-bin/luci-splash/" .. action) \ No newline at end of file
diff --git a/contrib/package/luci-splash/src/luci_splash/htdocs/index.html b/contrib/package/luci-splash/src/luci-splash/htdocs/index.html
index 58387a5fec..58387a5fec 100644
--- a/contrib/package/luci-splash/src/luci_splash/htdocs/index.html
+++ b/contrib/package/luci-splash/src/luci-splash/htdocs/index.html
diff --git a/contrib/package/luci-splash/src/luci-splash/splash.lua b/contrib/package/luci-splash/src/luci-splash/splash.lua
new file mode 100644
index 0000000000..c9a053df2c
--- /dev/null
+++ b/contrib/package/luci-splash/src/luci-splash/splash.lua
@@ -0,0 +1,93 @@
+package.path = "/usr/lib/lua/?.lua;/usr/lib/lua/?/init.lua;" .. package.path
+package.cpath = "/usr/lib/lua/?.so;" .. package.cpath
+
+require("ffluci.http")
+require("ffluci.sys")
+require("ffluci.model.uci")
+
+-- Init state session
+uci = ffluci.model.uci.Session("/var/state")
+
+
+-- Add a lease to state and invoke add_rule
+function add_lease(mac)
+ local key = uci:add("luci_splash", "lease")
+ uci:set("luci_splash", key, "mac", mac)
+ uci:set("luci_splash", key, "start", os.time())
+ add_rule(mac)
+end
+
+
+-- Remove a lease from state and invoke remove_rule
+function remove_lease(mac)
+ mac = mac:lower()
+
+ for k, v in pairs(uci:show("luci_splash").luci_splash) do
+ if v.mac:lower() == mac then
+ remove_rule(mac)
+ uci:del("luci_splash", k)
+ end
+ end
+end
+
+
+-- Add an iptables rule
+function add_rule(mac)
+ return os.execute("iptables -t nat -I luci_splash_leases -m mac --mac-source '"..mac.."' -j RETURN")
+end
+
+
+-- Remove an iptables rule
+function remove_rule(mac)
+ return os.execute("iptables -t nat -D luci_splash_leases -m mac --mac-source '"..mac.."' -j RETURN")
+end
+
+
+-- Get the MAC-Address of current user
+function ip4mac(ip)
+ local mac = nil
+
+ for i, l in ipairs(ffluci.sys.net.arptable()) do
+ if l["IP address"] == ip then
+ mac = l["HW address"]
+ end
+ end
+
+ return mac
+end
+
+
+-- Check whether a MAC-Address is listed in the lease state list
+function haslease(mac)
+ mac = mac:lower()
+
+ for k, v in pairs(uci:show("luci_splash").luci_splash) do
+ if v[".type"] == "lease" and v.mac and v.mac:lower() == mac then
+ return true
+ end
+ end
+
+ return false
+end
+
+
+-- Check whether a MAC-Address is whitelisted
+function iswhitelisted(mac)
+ mac = mac:lower()
+
+ for k, v in pairs(uci:show("luci_splash").luci_splash) do
+ if v[".type"] == "whitelist" and v.mac and v.mac:lower() == mac then
+ return true
+ end
+ end
+
+ return false
+end
+
+
+-- Returns a list of MAC-Addresses for which a rule is existing
+function listrules()
+ local cmd = "iptables -t nat -L luci_splash_leases | grep RETURN |"
+ cmd = cmd .. "egrep -io [0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+"
+ return ffluci.util.split(ffluci.sys.exec(cmd))
+end \ No newline at end of file
diff --git a/contrib/package/luci-splash/src/luci-splash/sync.lua b/contrib/package/luci-splash/src/luci-splash/sync.lua
new file mode 100644
index 0000000000..410b6608c3
--- /dev/null
+++ b/contrib/package/luci-splash/src/luci-splash/sync.lua
@@ -0,0 +1,39 @@
+#!/usr/bin/haserl --shell=luac --accept-none
+dofile("/usr/lib/luci-splash/splash.lua")
+
+local written = {}
+local time = os.time()
+
+-- Current leases in state files
+local leases = uci:show("luci_splash").luci_splash
+
+-- Convert leasetime to seconds
+local leasetime = tonumber(uci:get("luci_splash", "general", "leasetime")) * 3600
+
+-- Clean state file
+uci:revert("luci_splash")
+
+
+-- For all leases
+for k, v in pairs(uci:show("luci_splash")) do
+ if v[".type"] == "lease" then
+ if os.difftime(time, tonumber(v.start)) > leasetime then
+ -- Remove expired
+ remove_rule(v.mac)
+ else
+ -- Rewrite state
+ local n = uci:add("luci_splash", "lease")
+ uci:set("luci_splash", n, "mac", v.mac)
+ uci:set("luci_splash", n, "start", v.start)
+ written[v.mac] = 1
+ end
+ end
+end
+
+
+-- Delete rules without state
+for i, r in ipairs(listrules()) do
+ if not written[r] then
+ remove_rule(r)
+ end
+end \ No newline at end of file
diff --git a/contrib/package/luci-splash/src/luci_splash.cron b/contrib/package/luci-splash/src/luci_splash.cron
new file mode 100644
index 0000000000..81b51e9a95
--- /dev/null
+++ b/contrib/package/luci-splash/src/luci_splash.cron
@@ -0,0 +1 @@
+*/15 * * * * /usr/lib/luci-splash/sync.lua \ No newline at end of file
diff --git a/contrib/package/luci-splash/src/luci_splash.init b/contrib/package/luci-splash/src/luci_splash.init
index 049d121ea5..150f846f2f 100644
--- a/contrib/package/luci-splash/src/luci_splash.init
+++ b/contrib/package/luci-splash/src/luci_splash.init
@@ -19,14 +19,15 @@ iface_add() {
eval "$(ipcalc.sh $ipaddr $netmask)"
- iptables -t nat -A luci_splash -i "$iface" -s "$IP/$PREFIX" -j luci_splash_portal
+ iptables -t nat -A luci_splash -i "$iface" -s "$IP/$PREFIX" -j luci_splash_portal
+ iptables -t nat -A luci_splash_portal -i "$iface" -s "$IP/$PREFIX" -d "$ipaddr" -p tcp --dport 80 -j RETURN
}
blacklist_add() {
local cfg="$1"
config_get mac "$cfg" mac
- [ -n "$mac" ] && iptables -t nat -A luci_splash_portal -m mac --mac-source "$mac" -j REJECT
+ [ -n "$mac" ] && iptables -t nat -A luci_splash_portal -m mac --mac-source "$mac" -j DROP
}
whitelist_add() {
@@ -57,13 +58,13 @@ start() {
### Build the leases rule
iptables -t nat -A luci_splash_leases -p tcp --dport 80 -j REDIRECT --to-ports 8082
- iptables -t nat -A luci_splash_leases -j REJECT
+ iptables -t nat -A luci_splash_leases -j DROP
### Start the splash httpd
httpd -c /etc/luci_splash_httpd.conf -p 8082 -h /usr/lib/luci_splash/htdocs
### Sync leases
- /usr/lib/luci_splash/sync.lua
+ /usr/lib/luci-splash/sync.lua
### Hook in the chain
iptables -t nat -A prerouting_rule -j luci_splash
@@ -74,13 +75,13 @@ stop() {
iptables -t nat -D prerouting_rule -j luci_splash
### Clear subchains
- iptables -t nat -F luci_splash
- iptables -t nat -F luci_splash_portal
iptables -t nat -F luci_splash_leases
+ iptables -t nat -F luci_splash_portal
+ iptables -t nat -F luci_splash
### Delete subchains
- iptables -t nat -X luci_splash
- iptables -t nat -X luci_splash_portal
iptables -t nat -X luci_splash_leases
+ iptables -t nat -X luci_splash_portal
+ iptables -t nat -X luci_splash
}
diff --git a/contrib/package/luci-splash/src/luci_splash.uci b/contrib/package/luci-splash/src/luci_splash.uci
index cf1232b3b7..c4cfef5dd9 100644
--- a/contrib/package/luci-splash/src/luci_splash.uci
+++ b/contrib/package/luci-splash/src/luci_splash.uci
@@ -1,8 +1,2 @@
-config iface
- option network wldhcp
-
-config whitelist
- option mac 02:CA:FF:EE:BA:BE
-
-config blacklist
- option mac 03:CA:FF:EE:BA:BE \ No newline at end of file
+config core general
+ option leasetime 1 \ No newline at end of file
diff --git a/contrib/package/luci-splash/src/luci_splash/htdocs/cgi-bin/index.cgi b/contrib/package/luci-splash/src/luci_splash/htdocs/cgi-bin/index.cgi
deleted file mode 100644
index 0117198cfb..0000000000
--- a/contrib/package/luci-splash/src/luci_splash/htdocs/cgi-bin/index.cgi
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/haserl --shell=luac
-dofile("/usr/lib/luci_splash")
-
-require("ffluci.template")
-
-function dispatch()
- local mac = get_usermac()
- if not mac then
- return action_nodata()
- end
-
- if isblacklisted(mac) then
- return action_blocked()
- end
-
- if iswhitelisted(mac) or haslease(mac) then
- return action_allowed()
- end
-
- return action_splash(mac)
-end
-
-function action_splash(mac)
- if ffluci.http.formvalue("activate") then
- add_lease(mac)
- ffluci.http.textheader()
- print("Got splashed!")
- else
- ffluci.http.textheader()
- print("Get splashed!")
- end
-end
-
-function action_allowed()
- ffluci.http.textheader()
- print("Already allowed!")
-end
-
-function action_blocked()
- ffluci.http.textheader()
- print("Blocked!")
-end
-
-function action_nodata()
- ffluci.http.textheader()
- print("No data!")
-end
-
-dispatch() \ No newline at end of file
diff --git a/contrib/package/luci-splash/src/luci_splash/splash.lua b/contrib/package/luci-splash/src/luci_splash/splash.lua
deleted file mode 100644
index b659d20011..0000000000
--- a/contrib/package/luci-splash/src/luci_splash/splash.lua
+++ /dev/null
@@ -1,74 +0,0 @@
-package.path = "/usr/lib/lua/?.lua;/usr/lib/lua/?/init.lua;" .. package.path
-package.cpath = "/usr/lib/lua/?.so;" .. package.cpath
-
-require("ffluci.http")
-require("ffluci.sys")
-require("ffluci.model.uci")
-
-ucis = ffluci.model.uci.Session("/var/state")
-
-function add_lease(mac)
- local key = ucis:add("luci_splash", "lease")
- ucis:set("luci_splash", key, "mac", mac)
- add_rule(mac)
-end
-
-function add_rule(mac)
- return os.execute("iptables -t nat -I luci_splash_leases -m mac --source-mac '"..mac.."' -j RETURN")
-end
-
-function remove_rule(mac)
- return os.execute("iptables -t nat -D luci_splash_leases -m mac --source-mac '"..mac.."' -j RETURN")
-end
-
-function get_usermac()
- local ip = ffluci.http.remote_addr()
- local mac = nil
-
- for i, l in ipairs(ffluci.sys.net.arptable()) do
- if l["IP address"] == ip then
- mac = l["HW address"]
- end
- end
-
- return mac
-end
-
-function haslease(mac)
- mac = mac:lower()
- local list = ucis:show("luci_splash").luci_splash
-
- for k, v in pairs(list) do
- if v[".type"] == "lease" and v.mac and v.mac:lower() == mac then
- return true
- end
- end
-
- return false
-end
-
-function isblacklisted(mac)
- mac = mac:lower()
- local list = ucis:show("luci_splash").luci_splash
-
- for k, v in pairs(list) do
- if v[".type"] == "blacklist" and v.mac and v.mac:lower() == mac then
- return true
- end
- end
-
- return false
-end
-
-function iswhitelisted(mac)
- mac = mac:lower()
- local list = ucis:show("luci_splash").luci_splash
-
- for k, v in pairs(list) do
- if v[".type"] == "whitelist" and v.mac and v.mac:lower() == mac then
- return true
- end
- end
-
- return false
-end \ No newline at end of file
diff --git a/contrib/package/luci-splash/src/luci_splash/sync.lua b/contrib/package/luci-splash/src/luci_splash/sync.lua
deleted file mode 100644
index fd32a1ca16..0000000000
--- a/contrib/package/luci-splash/src/luci_splash/sync.lua
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/haserl --shell=luac --accept-none
-dofile("splash.lua")
-
diff --git a/contrib/package/luci-splash/src/luci_splash_httpd.conf b/contrib/package/luci-splash/src/luci_splash_httpd.conf
index f481c22ce8..6007e80dba 100644
--- a/contrib/package/luci-splash/src/luci_splash_httpd.conf
+++ b/contrib/package/luci-splash/src/luci_splash_httpd.conf
@@ -1 +1 @@
-E404:/index.html \ No newline at end of file
+E404:index.html \ No newline at end of file
diff --git a/core/contrib/uci/luci b/core/contrib/uci/luci
index 10a05bdeea..a3603d7ff3 100644
--- a/core/contrib/uci/luci
+++ b/core/contrib/uci/luci
@@ -24,6 +24,7 @@ config event uci_oncommit
option httpd "/etc/init.d/httpd restart"
option fstab "/etc/init.d/fstab restart"
option qos "/etc/init.d/qos restart"
+ option luci_splash "/etc/init.d/luci_splash restart"
config internal languages
option de "Deutsch"
diff --git a/core/src/ffluci/init.lua b/core/src/ffluci/init.lua
index dbecf57e40..3b5ea14292 100644
--- a/core/src/ffluci/init.lua
+++ b/core/src/ffluci/init.lua
@@ -25,7 +25,7 @@ limitations under the License.
]]--
module("ffluci", package.seeall)
-__version__ = "0.2"
+__version__ = "0.3"
__appname__ = "FFLuCI"
dispatch = require("ffluci.dispatcher").httpdispatch
diff --git a/module/admin-core/contrib/luci-splash b/module/admin-core/contrib/luci-splash
new file mode 100644
index 0000000000..57fa4b6092
--- /dev/null
+++ b/module/admin-core/contrib/luci-splash
@@ -0,0 +1,4 @@
+#!/bin/sh
+echo "Status: 302 Found"
+echo "Location: ffluci/public/splash$PATH_INFO"
+echo \ No newline at end of file
diff --git a/module/admin-core/src/model/cbi/admin_network/splash.lua b/module/admin-core/src/model/cbi/admin_services/splash.lua
index 497d394ee2..d3c3f0ae79 100644
--- a/module/admin-core/src/model/cbi/admin_network/splash.lua
+++ b/module/admin-core/src/model/cbi/admin_services/splash.lua
@@ -3,6 +3,9 @@ require("ffluci.model.uci")
m = Map("luci_splash", "Client-Splash", [[Client-Splash ist das Freifunk Hotspot-Authentifizierungs-System.]])
+s = m:section(NamedSection, "general", "core", "Allgemein")
+s:option(Value, "leasetime", "Freigabezeit", "h")
+
s = m:section(TypedSection, "iface", "Schnittstellen")
s.addremove = true
s.anonymous = true
diff --git a/module/admin-core/src/model/menu/00admin.lua b/module/admin-core/src/model/menu/00admin.lua
index 42c185937d..3754a5bc8b 100644
--- a/module/admin-core/src/model/menu/00admin.lua
+++ b/module/admin-core/src/model/menu/00admin.lua
@@ -18,6 +18,9 @@ end
act("httpd", "HTTP-Server")
act("dropbear", "SSH-Server")
act("dnsmasq", "Dnsmasq")
+if isfile("/etc/config/luci_splash") then
+ act("splash", "Client-Splash")
+end
add("admin", "network", "Netzwerk", 50)
act("vlan", "Switch")
@@ -27,11 +30,6 @@ act("ptp", "PPPoE / PPTP")
act("routes", "Statische Routen")
act("portfw", "Portweiterleitung")
act("firewall", "Firewall")
-
-if isfile("/etc/config/luci_splash") then
- act("splash", "Client-Splash")
-end
-
if isfile("/etc/config/qos") then
act("qos", "Quality of Service")
end
diff --git a/module/admin-core/src/view/admin_system/reboot.htm b/module/admin-core/src/view/admin_system/reboot.htm
index df855e49c3..b6c38b75c4 100644
--- a/module/admin-core/src/view/admin_system/reboot.htm
+++ b/module/admin-core/src/view/admin_system/reboot.htm
@@ -6,6 +6,6 @@
<p><a href="<%=controller%>/admin/system/reboot?reboot=1"><%:reboot_do Neustart durchführen%></a></p>
<% else %>
<p><%:reboot_running Bitte warten: Neustart wird durchgeführt...%></p>
-<script type="text/javascript">setTimeout("location='<%=controller%>/admin'", 30000)</script>
+<script type="text/javascript">setTimeout("location='<%=controller%>/admin'", 45000)</script>
<% end %>
<%+footer%> \ No newline at end of file