fff-web: add web interface package

Signed-off-by: Tim Niemeyer <tim.niemeyer@mastersword.de>
Reviewed-by: Tobias Klaus <tk+ff@meskal.net>
Reviewed-by: Steffen Pankratz <kratz00@gmx.de>
This commit is contained in:
Tim Niemeyer 2015-12-13 22:16:10 +01:00 committed by Steffen Pankratz
parent 866d2ce320
commit bd9420b5fb
28 changed files with 3324 additions and 2 deletions

View File

@ -0,0 +1,42 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=fff-web
PKG_VERSION:=0.0.1
PKG_RELEASE:=1
PKG_BUILD_DIR:=$(BUILD_DIR)/fff-web
include $(INCLUDE_DIR)/package.mk
define Package/fff-web
SECTION:=base
CATEGORY:=Freifunk
TITLE:= Freifunk-Franken Webinterface
URL:=http://www.freifunk-franken.de
DEPENDS:=+uhttpd +haserl +uhttpd-mod-tls +px5g +simple-tc
endef
define Package/fff-web/description
This is the Webinterface for the Freifunk Franken Firmware
endef
define Build/Prepare
echo "all: " > $(PKG_BUILD_DIR)/Makefile
endef
define Build/Configure
# nothing
endef
define Build/Compile
# nothing
endef
define Package/fff-web/install
$(CP) ./files/* $(1)/
ifeq ($(CONFIG_PACKAGE_fff-nodewatcher),y)
ln -s ../../tmp/crawldata/node.data $(1)/www/public/node.data
endif
endef
$(eval $(call BuildPackage,fff-web))

View File

@ -0,0 +1,35 @@
config uhttpd public
list listen_http 80
option home /www/public
option rfc1918_filter 1
option cgi_prefix /cgi-bin
option script_timeout 60
option network_timeout 30
option tcp_keepalive 1
option config "_"
config uhttpd ssl
list listen_https 443
option home /www/ssl
option rfc1918_filter 1
option cert /etc/uhttpd.crt
option key /etc/uhttpd.key
option cgi_prefix /cgi-bin
option script_timeout 60
option network_timeout 30
option tcp_keepalive 1
option config "/etc/httpd.conf"
# Certificate defaults for px5g key generator
config cert px5g
# Validity time
option days 1400
# RSA key size
option bits 2048
# Common name
option commonname OpenWrt

View File

@ -0,0 +1 @@
/:root:$p$root

View File

@ -0,0 +1,63 @@
#!/usr/bin/haserl
<% echo -en "content-type: text/html\r\n\r\n" %>
<% . /etc/firmware_release %>
<!DOCTYPE html>
<html lang="de"><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>info</title>
<link rel="stylesheet" href="/css/pure-min.css">
<link rel="stylesheet" href="/css/side-menu.css">
<link rel="stylesheet" href="/css/grids-responsive-min.css">
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<div class="header">
<div class="home-menu pure-menu pure-menu-open pure-menu-horizontal pure-menu-fixed">
<a class="pure-menu-heading" href="http://www.freifunk-franken.de">freifunk-franken.de</a>
<ul>
<%
contact="$(uci get -q freifunk.@settings[0].contact)"
if [ -n "$contact" ]; then
echo " <li><a href='#'>Kontakt: $contact</a></li>"
fi
geo="$(uci get -q freifunk.@settings[0].geo)"
if [ -n "$geo" ]; then
lat="${geo%% *}" lon="${geo##* }"
echo " <li><a href=\"https://www.openstreetmap.org?mlat=$lat&mlon=$lon&zoom=17\">Position: ${lat:0:8}N, ${lon:0:8}E</a></li>"
fi
%>
<li><form action="https://<% echo -n "$HTTP_HOST" %>"><button type="submit" class="pure-button">Login</button></form></li>
</ul>
</div>
</div>
<div class="header">
<%
echo " <h1>$(uci get -q freifunk.@settings[0].name)</h1>"
%>
<h2>Firmware Version <% echo -n $FIRMWARE_VERSION %></h2>
</div>
<div class="content">
<div class="pure-g" style="text-align:center;">
<div class="pure-u-1 pure-u-md-1-3">
<div class="blockhead"></div>
<h2>Nachbarknoten</h2>
<h3><% echo -n $(cat /sys/kernel/debug/batman_adv/bat0/originators | grep '^[0-9a-f]' | cut -b 37-53 | sort | uniq | wc -l 2> /dev/null) %></h3>
</div>
<div class="pure-u-1 pure-u-md-1-3">
<div class="blockhead"></div>
<h2>Alle Knoten</h2>
<h3><% echo -n $((`cat /sys/kernel/debug/batman_adv/bat0/transtable_global | grep '^ [^ ]' | cut -b 39-55 | sort | uniq | wc -l 2> /dev/null`+1)) %></h3>
</div>
<div class="pure-u-1 pure-u-md-1-3">
<div class="blockhead"></div>
<h2>Lokale Clients</h2>
<h3><% echo -n $(cat /sys/kernel/debug/batman_adv/bat0/transtable_local 2> /dev/null | grep -c 'W') %></h3>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,491 @@
/*!
Pure v0.5.0
Copyright 2014 Yahoo! Inc. All rights reserved.
Licensed under the BSD License.
https://github.com/yui/pure/blob/master/LICENSE.md
*/
@media screen and (min-width:35.5em){
.pure-u-sm-1,.pure-u-sm-1-1,.pure-u-sm-1-2,.pure-u-sm-1-3,.pure-u-sm-2-3,.pure-u-sm-1-4,.pure-u-sm-3-4,.pure-u-sm-1-5,.pure-u-sm-2-5,.pure-u-sm-3-5,.pure-u-sm-4-5,.pure-u-sm-5-5,.pure-u-sm-1-6,.pure-u-sm-5-6,.pure-u-sm-1-8,.pure-u-sm-3-8,.pure-u-sm-5-8,.pure-u-sm-7-8,.pure-u-sm-1-12,.pure-u-sm-5-12,.pure-u-sm-7-12,.pure-u-sm-11-12,.pure-u-sm-1-24,.pure-u-sm-2-24,.pure-u-sm-3-24,.pure-u-sm-4-24,.pure-u-sm-5-24,.pure-u-sm-6-24,.pure-u-sm-7-24,.pure-u-sm-8-24,.pure-u-sm-9-24,.pure-u-sm-10-24,.pure-u-sm-11-24,.pure-u-sm-12-24,.pure-u-sm-13-24,.pure-u-sm-14-24,.pure-u-sm-15-24,.pure-u-sm-16-24,.pure-u-sm-17-24,.pure-u-sm-18-24,.pure-u-sm-19-24,.pure-u-sm-20-24,.pure-u-sm-21-24,.pure-u-sm-22-24,.pure-u-sm-23-24,.pure-u-sm-24-24{
display:inline-block;
*display:inline;
zoom:1;
letter-spacing:normal;
word-spacing:normal;
vertical-align:top;
text-rendering:auto
}
.pure-u-sm-1-24{
width:4.1667%;
*width:4.1357%
}
.pure-u-sm-1-12,.pure-u-sm-2-24{
width:8.3333%;
*width:8.3023%
}
.pure-u-sm-1-8,.pure-u-sm-3-24{
width:12.5%;
*width:12.469%
}
.pure-u-sm-1-6,.pure-u-sm-4-24{
width:16.6667%;
*width:16.6357%
}
.pure-u-sm-1-5{
width:20%;
*width:19.969%
}
.pure-u-sm-5-24{
width:20.8333%;
*width:20.8023%
}
.pure-u-sm-1-4,.pure-u-sm-6-24{
width:25%;
*width:24.969%
}
.pure-u-sm-7-24{
width:29.1667%;
*width:29.1357%
}
.pure-u-sm-1-3,.pure-u-sm-8-24{
width:33.3333%;
*width:33.3023%
}
.pure-u-sm-3-8,.pure-u-sm-9-24{
width:37.5%;
*width:37.469%
}
.pure-u-sm-2-5{
width:40%;
*width:39.969%
}
.pure-u-sm-5-12,.pure-u-sm-10-24{
width:41.6667%;
*width:41.6357%
}
.pure-u-sm-11-24{
width:45.8333%;
*width:45.8023%
}
.pure-u-sm-1-2,.pure-u-sm-12-24{
width:50%;
*width:49.969%
}
.pure-u-sm-13-24{
width:54.1667%;
*width:54.1357%
}
.pure-u-sm-7-12,.pure-u-sm-14-24{
width:58.3333%;
*width:58.3023%
}
.pure-u-sm-3-5{
width:60%;
*width:59.969%
}
.pure-u-sm-5-8,.pure-u-sm-15-24{
width:62.5%;
*width:62.469%
}
.pure-u-sm-2-3,.pure-u-sm-16-24{
width:66.6667%;
*width:66.6357%
}
.pure-u-sm-17-24{
width:70.8333%;
*width:70.8023%
}
.pure-u-sm-3-4,.pure-u-sm-18-24{
width:75%;
*width:74.969%
}
.pure-u-sm-19-24{
width:79.1667%;
*width:79.1357%
}
.pure-u-sm-4-5{
width:80%;
*width:79.969%
}
.pure-u-sm-5-6,.pure-u-sm-20-24{
width:83.3333%;
*width:83.3023%
}
.pure-u-sm-7-8,.pure-u-sm-21-24{
width:87.5%;
*width:87.469%
}
.pure-u-sm-11-12,.pure-u-sm-22-24{
width:91.6667%;
*width:91.6357%
}
.pure-u-sm-23-24{
width:95.8333%;
*width:95.8023%
}
.pure-u-sm-1,.pure-u-sm-1-1,.pure-u-sm-5-5,.pure-u-sm-24-24{
width:100%
}
}@media screen and (min-width:48em){
.pure-u-md-1,.pure-u-md-1-1,.pure-u-md-1-2,.pure-u-md-1-3,.pure-u-md-2-3,.pure-u-md-1-4,.pure-u-md-3-4,.pure-u-md-1-5,.pure-u-md-2-5,.pure-u-md-3-5,.pure-u-md-4-5,.pure-u-md-5-5,.pure-u-md-1-6,.pure-u-md-5-6,.pure-u-md-1-8,.pure-u-md-3-8,.pure-u-md-5-8,.pure-u-md-7-8,.pure-u-md-1-12,.pure-u-md-5-12,.pure-u-md-7-12,.pure-u-md-11-12,.pure-u-md-1-24,.pure-u-md-2-24,.pure-u-md-3-24,.pure-u-md-4-24,.pure-u-md-5-24,.pure-u-md-6-24,.pure-u-md-7-24,.pure-u-md-8-24,.pure-u-md-9-24,.pure-u-md-10-24,.pure-u-md-11-24,.pure-u-md-12-24,.pure-u-md-13-24,.pure-u-md-14-24,.pure-u-md-15-24,.pure-u-md-16-24,.pure-u-md-17-24,.pure-u-md-18-24,.pure-u-md-19-24,.pure-u-md-20-24,.pure-u-md-21-24,.pure-u-md-22-24,.pure-u-md-23-24,.pure-u-md-24-24{
display:inline-block;
*display:inline;
zoom:1;
letter-spacing:normal;
word-spacing:normal;
vertical-align:top;
text-rendering:auto
}
.pure-u-md-1-24{
width:4.1667%;
*width:4.1357%
}
.pure-u-md-1-12,.pure-u-md-2-24{
width:8.3333%;
*width:8.3023%
}
.pure-u-md-1-8,.pure-u-md-3-24{
width:12.5%;
*width:12.469%
}
.pure-u-md-1-6,.pure-u-md-4-24{
width:16.6667%;
*width:16.6357%
}
.pure-u-md-1-5{
width:20%;
*width:19.969%
}
.pure-u-md-5-24{
width:20.8333%;
*width:20.8023%
}
.pure-u-md-1-4,.pure-u-md-6-24{
width:25%;
*width:24.969%
}
.pure-u-md-7-24{
width:29.1667%;
*width:29.1357%
}
.pure-u-md-1-3,.pure-u-md-8-24{
width:33.3333%;
*width:33.3023%
}
.pure-u-md-3-8,.pure-u-md-9-24{
width:37.5%;
*width:37.469%
}
.pure-u-md-2-5{
width:40%;
*width:39.969%
}
.pure-u-md-5-12,.pure-u-md-10-24{
width:41.6667%;
*width:41.6357%
}
.pure-u-md-11-24{
width:45.8333%;
*width:45.8023%
}
.pure-u-md-1-2,.pure-u-md-12-24{
width:50%;
*width:49.969%
}
.pure-u-md-13-24{
width:54.1667%;
*width:54.1357%
}
.pure-u-md-7-12,.pure-u-md-14-24{
width:58.3333%;
*width:58.3023%
}
.pure-u-md-3-5{
width:60%;
*width:59.969%
}
.pure-u-md-5-8,.pure-u-md-15-24{
width:62.5%;
*width:62.469%
}
.pure-u-md-2-3,.pure-u-md-16-24{
width:66.6667%;
*width:66.6357%
}
.pure-u-md-17-24{
width:70.8333%;
*width:70.8023%
}
.pure-u-md-3-4,.pure-u-md-18-24{
width:75%;
*width:74.969%
}
.pure-u-md-19-24{
width:79.1667%;
*width:79.1357%
}
.pure-u-md-4-5{
width:80%;
*width:79.969%
}
.pure-u-md-5-6,.pure-u-md-20-24{
width:83.3333%;
*width:83.3023%
}
.pure-u-md-7-8,.pure-u-md-21-24{
width:87.5%;
*width:87.469%
}
.pure-u-md-11-12,.pure-u-md-22-24{
width:91.6667%;
*width:91.6357%
}
.pure-u-md-23-24{
width:95.8333%;
*width:95.8023%
}
.pure-u-md-1,.pure-u-md-1-1,.pure-u-md-5-5,.pure-u-md-24-24{
width:100%
}
}@media screen and (min-width:64em){
.pure-u-lg-1,.pure-u-lg-1-1,.pure-u-lg-1-2,.pure-u-lg-1-3,.pure-u-lg-2-3,.pure-u-lg-1-4,.pure-u-lg-3-4,.pure-u-lg-1-5,.pure-u-lg-2-5,.pure-u-lg-3-5,.pure-u-lg-4-5,.pure-u-lg-5-5,.pure-u-lg-1-6,.pure-u-lg-5-6,.pure-u-lg-1-8,.pure-u-lg-3-8,.pure-u-lg-5-8,.pure-u-lg-7-8,.pure-u-lg-1-12,.pure-u-lg-5-12,.pure-u-lg-7-12,.pure-u-lg-11-12,.pure-u-lg-1-24,.pure-u-lg-2-24,.pure-u-lg-3-24,.pure-u-lg-4-24,.pure-u-lg-5-24,.pure-u-lg-6-24,.pure-u-lg-7-24,.pure-u-lg-8-24,.pure-u-lg-9-24,.pure-u-lg-10-24,.pure-u-lg-11-24,.pure-u-lg-12-24,.pure-u-lg-13-24,.pure-u-lg-14-24,.pure-u-lg-15-24,.pure-u-lg-16-24,.pure-u-lg-17-24,.pure-u-lg-18-24,.pure-u-lg-19-24,.pure-u-lg-20-24,.pure-u-lg-21-24,.pure-u-lg-22-24,.pure-u-lg-23-24,.pure-u-lg-24-24{
display:inline-block;
*display:inline;
zoom:1;
letter-spacing:normal;
word-spacing:normal;
vertical-align:top;
text-rendering:auto
}
.pure-u-lg-1-24{
width:4.1667%;
*width:4.1357%
}
.pure-u-lg-1-12,.pure-u-lg-2-24{
width:8.3333%;
*width:8.3023%
}
.pure-u-lg-1-8,.pure-u-lg-3-24{
width:12.5%;
*width:12.469%
}
.pure-u-lg-1-6,.pure-u-lg-4-24{
width:16.6667%;
*width:16.6357%
}
.pure-u-lg-1-5{
width:20%;
*width:19.969%
}
.pure-u-lg-5-24{
width:20.8333%;
*width:20.8023%
}
.pure-u-lg-1-4,.pure-u-lg-6-24{
width:25%;
*width:24.969%
}
.pure-u-lg-7-24{
width:29.1667%;
*width:29.1357%
}
.pure-u-lg-1-3,.pure-u-lg-8-24{
width:33.3333%;
*width:33.3023%
}
.pure-u-lg-3-8,.pure-u-lg-9-24{
width:37.5%;
*width:37.469%
}
.pure-u-lg-2-5{
width:40%;
*width:39.969%
}
.pure-u-lg-5-12,.pure-u-lg-10-24{
width:41.6667%;
*width:41.6357%
}
.pure-u-lg-11-24{
width:45.8333%;
*width:45.8023%
}
.pure-u-lg-1-2,.pure-u-lg-12-24{
width:50%;
*width:49.969%
}
.pure-u-lg-13-24{
width:54.1667%;
*width:54.1357%
}
.pure-u-lg-7-12,.pure-u-lg-14-24{
width:58.3333%;
*width:58.3023%
}
.pure-u-lg-3-5{
width:60%;
*width:59.969%
}
.pure-u-lg-5-8,.pure-u-lg-15-24{
width:62.5%;
*width:62.469%
}
.pure-u-lg-2-3,.pure-u-lg-16-24{
width:66.6667%;
*width:66.6357%
}
.pure-u-lg-17-24{
width:70.8333%;
*width:70.8023%
}
.pure-u-lg-3-4,.pure-u-lg-18-24{
width:75%;
*width:74.969%
}
.pure-u-lg-19-24{
width:79.1667%;
*width:79.1357%
}
.pure-u-lg-4-5{
width:80%;
*width:79.969%
}
.pure-u-lg-5-6,.pure-u-lg-20-24{
width:83.3333%;
*width:83.3023%
}
.pure-u-lg-7-8,.pure-u-lg-21-24{
width:87.5%;
*width:87.469%
}
.pure-u-lg-11-12,.pure-u-lg-22-24{
width:91.6667%;
*width:91.6357%
}
.pure-u-lg-23-24{
width:95.8333%;
*width:95.8023%
}
.pure-u-lg-1,.pure-u-lg-1-1,.pure-u-lg-5-5,.pure-u-lg-24-24{
width:100%
}
}@media screen and (min-width:80em){
.pure-u-xl-1,.pure-u-xl-1-1,.pure-u-xl-1-2,.pure-u-xl-1-3,.pure-u-xl-2-3,.pure-u-xl-1-4,.pure-u-xl-3-4,.pure-u-xl-1-5,.pure-u-xl-2-5,.pure-u-xl-3-5,.pure-u-xl-4-5,.pure-u-xl-5-5,.pure-u-xl-1-6,.pure-u-xl-5-6,.pure-u-xl-1-8,.pure-u-xl-3-8,.pure-u-xl-5-8,.pure-u-xl-7-8,.pure-u-xl-1-12,.pure-u-xl-5-12,.pure-u-xl-7-12,.pure-u-xl-11-12,.pure-u-xl-1-24,.pure-u-xl-2-24,.pure-u-xl-3-24,.pure-u-xl-4-24,.pure-u-xl-5-24,.pure-u-xl-6-24,.pure-u-xl-7-24,.pure-u-xl-8-24,.pure-u-xl-9-24,.pure-u-xl-10-24,.pure-u-xl-11-24,.pure-u-xl-12-24,.pure-u-xl-13-24,.pure-u-xl-14-24,.pure-u-xl-15-24,.pure-u-xl-16-24,.pure-u-xl-17-24,.pure-u-xl-18-24,.pure-u-xl-19-24,.pure-u-xl-20-24,.pure-u-xl-21-24,.pure-u-xl-22-24,.pure-u-xl-23-24,.pure-u-xl-24-24{
display:inline-block;
*display:inline;
zoom:1;
letter-spacing:normal;
word-spacing:normal;
vertical-align:top;
text-rendering:auto
}
.pure-u-xl-1-24{
width:4.1667%;
*width:4.1357%
}
.pure-u-xl-1-12,.pure-u-xl-2-24{
width:8.3333%;
*width:8.3023%
}
.pure-u-xl-1-8,.pure-u-xl-3-24{
width:12.5%;
*width:12.469%
}
.pure-u-xl-1-6,.pure-u-xl-4-24{
width:16.6667%;
*width:16.6357%
}
.pure-u-xl-1-5{
width:20%;
*width:19.969%
}
.pure-u-xl-5-24{
width:20.8333%;
*width:20.8023%
}
.pure-u-xl-1-4,.pure-u-xl-6-24{
width:25%;
*width:24.969%
}
.pure-u-xl-7-24{
width:29.1667%;
*width:29.1357%
}
.pure-u-xl-1-3,.pure-u-xl-8-24{
width:33.3333%;
*width:33.3023%
}
.pure-u-xl-3-8,.pure-u-xl-9-24{
width:37.5%;
*width:37.469%
}
.pure-u-xl-2-5{
width:40%;
*width:39.969%
}
.pure-u-xl-5-12,.pure-u-xl-10-24{
width:41.6667%;
*width:41.6357%
}
.pure-u-xl-11-24{
width:45.8333%;
*width:45.8023%
}
.pure-u-xl-1-2,.pure-u-xl-12-24{
width:50%;
*width:49.969%
}
.pure-u-xl-13-24{
width:54.1667%;
*width:54.1357%
}
.pure-u-xl-7-12,.pure-u-xl-14-24{
width:58.3333%;
*width:58.3023%
}
.pure-u-xl-3-5{
width:60%;
*width:59.969%
}
.pure-u-xl-5-8,.pure-u-xl-15-24{
width:62.5%;
*width:62.469%
}
.pure-u-xl-2-3,.pure-u-xl-16-24{
width:66.6667%;
*width:66.6357%
}
.pure-u-xl-17-24{
width:70.8333%;
*width:70.8023%
}
.pure-u-xl-3-4,.pure-u-xl-18-24{
width:75%;
*width:74.969%
}
.pure-u-xl-19-24{
width:79.1667%;
*width:79.1357%
}
.pure-u-xl-4-5{
width:80%;
*width:79.969%
}
.pure-u-xl-5-6,.pure-u-xl-20-24{
width:83.3333%;
*width:83.3023%
}
.pure-u-xl-7-8,.pure-u-xl-21-24{
width:87.5%;
*width:87.469%
}
.pure-u-xl-11-12,.pure-u-xl-22-24{
width:91.6667%;
*width:91.6357%
}
.pure-u-xl-23-24{
width:95.8333%;
*width:95.8023%
}
.pure-u-xl-1,.pure-u-xl-1-1,.pure-u-xl-5-5,.pure-u-xl-24-24{
width:100%
}
}

View File

@ -0,0 +1,892 @@
/*!
Pure v0.5.0
Copyright 2014 Yahoo! Inc. All rights reserved.
Licensed under the BSD License.
https://github.com/yui/pure/blob/master/LICENSE.md
*/
/*!
normalize.css v1.1.3 | MIT License | git.io/normalize
Copyright (c) Nicolas Gallagher and Jonathan Neal
*/
/*! normalize.css v1.1.3 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{
display:block
}
audio,canvas,video{
display:inline-block;
*display:inline;
*zoom:1
}
audio:not([controls]){
display:none;
height:0
}
[hidden]{
display:none
}
html{
font-size:100%;
-ms-text-size-adjust:100%;
-webkit-text-size-adjust:100%
}
html,button,input,select,textarea{
font-family:sans-serif
}
body{
margin:0
}
a:focus{
outline:thin dotted
}
a:active,a:hover{
outline:0
}
h1{
font-size:2em;
margin:.67em 0
}
h2{
font-size:1.5em;
margin:.83em 0
}
h3{
font-size:1.17em;
margin:1em 0
}
h4{
font-size:1em;
margin:1.33em 0
}
h5{
font-size:.83em;
margin:1.67em 0
}
h6{
font-size:.67em;
margin:2.33em 0
}
abbr[title]{
border-bottom:1px dotted
}
b,strong{
font-weight:700
}
blockquote{
margin:1em 40px
}
dfn{
font-style:italic
}
hr{
-moz-box-sizing:content-box;
box-sizing:content-box;
height:0
}
mark{
background:#ff0;
color:#000
}
p,pre{
margin:1em 0
}
code,kbd,pre,samp{
font-family:monospace,serif;
_font-family:'courier new',monospace;
font-size:1em
}
pre{
white-space:pre;
white-space:pre-wrap;
word-wrap:break-word
}
q{
quotes:none
}
q:before,q:after{
content:'';
content:none
}
small{
font-size:80%
}
sub,sup{
font-size:75%;
line-height:0;
position:relative;
vertical-align:baseline
}
sup{
top:-.5em
}
sub{
bottom:-.25em
}
dl,menu,ol,ul{
margin:1em 0
}
dd{
margin:0 0 0 40px
}
menu,ol,ul{
padding:0 0 0 40px
}
nav ul,nav ol{
list-style:none;
list-style-image:none
}
img{
border:0;
-ms-interpolation-mode:bicubic
}
svg:not(:root){
overflow:hidden
}
figure{
margin:0
}
form{
margin:0
}
fieldset{
border:1px solid silver;
margin:0 2px;
padding:.35em .625em .75em
}
legend{
border:0;
padding:0;
white-space:normal;
*margin-left:-7px
}
button,input,select,textarea{
font-size:100%;
margin:0;
vertical-align:baseline;
*vertical-align:middle
}
button,input{
line-height:normal
}
button,select{
text-transform:none
}
button,html input[type=button],input[type=reset],input[type=submit]{
-webkit-appearance:button;
cursor:pointer;
*overflow:visible
}
button[disabled],html input[disabled]{
cursor:default
}
input[type=checkbox],input[type=radio]{
box-sizing:border-box;
padding:0;
*height:13px;
*width:13px
}
input[type=search]{
-webkit-appearance:textfield;
-moz-box-sizing:content-box;
-webkit-box-sizing:content-box;
box-sizing:content-box
}
input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{
-webkit-appearance:none
}
button::-moz-focus-inner,input::-moz-focus-inner{
border:0;
padding:0
}
textarea{
overflow:auto;
vertical-align:top
}
table{
border-collapse:collapse;
border-spacing:0
}
[hidden]{
display:none!important
}
.pure-img{
max-width:100%;
height:auto;
display:block
}
.pure-g{
letter-spacing:-.31em;
*letter-spacing:normal;
*word-spacing:-.43em;
text-rendering:optimizespeed;
font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;
display:-webkit-flex;
-webkit-flex-flow:row wrap;
display:-ms-flexbox;
-ms-flex-flow:row wrap
}
.opera-only :-o-prefocus,.pure-g{
word-spacing:-.43em
}
.pure-u{
display:inline-block;
*display:inline;
zoom:1;
letter-spacing:normal;
word-spacing:normal;
vertical-align:top;
text-rendering:auto
}
.pure-g [class *="pure-u"]{
font-family:sans-serif
}
.pure-u-1,.pure-u-1-1,.pure-u-1-2,.pure-u-1-3,.pure-u-2-3,.pure-u-1-4,.pure-u-3-4,.pure-u-1-5,.pure-u-2-5,.pure-u-3-5,.pure-u-4-5,.pure-u-5-5,.pure-u-1-6,.pure-u-5-6,.pure-u-1-8,.pure-u-3-8,.pure-u-5-8,.pure-u-7-8,.pure-u-1-12,.pure-u-5-12,.pure-u-7-12,.pure-u-11-12,.pure-u-1-24,.pure-u-2-24,.pure-u-3-24,.pure-u-4-24,.pure-u-5-24,.pure-u-6-24,.pure-u-7-24,.pure-u-8-24,.pure-u-9-24,.pure-u-10-24,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24{
display:inline-block;
*display:inline;
zoom:1;
letter-spacing:normal;
word-spacing:normal;
vertical-align:top;
text-rendering:auto
}
.pure-u-1-24{
width:4.1667%;
*width:4.1357%
}
.pure-u-1-12,.pure-u-2-24{
width:8.3333%;
*width:8.3023%
}
.pure-u-1-8,.pure-u-3-24{
width:12.5%;
*width:12.469%
}
.pure-u-1-6,.pure-u-4-24{
width:16.6667%;
*width:16.6357%
}
.pure-u-1-5{
width:20%;
*width:19.969%
}
.pure-u-5-24{
width:20.8333%;
*width:20.8023%
}
.pure-u-1-4,.pure-u-6-24{
width:25%;
*width:24.969%
}
.pure-u-7-24{
width:29.1667%;
*width:29.1357%
}
.pure-u-1-3,.pure-u-8-24{
width:33.3333%;
*width:33.3023%
}
.pure-u-3-8,.pure-u-9-24{
width:37.5%;
*width:37.469%
}
.pure-u-2-5{
width:40%;
*width:39.969%
}
.pure-u-5-12,.pure-u-10-24{
width:41.6667%;
*width:41.6357%
}
.pure-u-11-24{
width:45.8333%;
*width:45.8023%
}
.pure-u-1-2,.pure-u-12-24{
width:50%;
*width:49.969%
}
.pure-u-13-24{
width:54.1667%;
*width:54.1357%
}
.pure-u-7-12,.pure-u-14-24{
width:58.3333%;
*width:58.3023%
}
.pure-u-3-5{
width:60%;
*width:59.969%
}
.pure-u-5-8,.pure-u-15-24{
width:62.5%;
*width:62.469%
}
.pure-u-2-3,.pure-u-16-24{
width:66.6667%;
*width:66.6357%
}
.pure-u-17-24{
width:70.8333%;
*width:70.8023%
}
.pure-u-3-4,.pure-u-18-24{
width:75%;
*width:74.969%
}
.pure-u-19-24{
width:79.1667%;
*width:79.1357%
}
.pure-u-4-5{
width:80%;
*width:79.969%
}
.pure-u-5-6,.pure-u-20-24{
width:83.3333%;
*width:83.3023%
}
.pure-u-7-8,.pure-u-21-24{
width:87.5%;
*width:87.469%
}
.pure-u-11-12,.pure-u-22-24{
width:91.6667%;
*width:91.6357%
}
.pure-u-23-24{
width:95.8333%;
*width:95.8023%
}
.pure-u-1,.pure-u-1-1,.pure-u-5-5,.pure-u-24-24{
width:100%
}
.pure-button{
display:inline-block;
*display:inline;
zoom:1;
line-height:normal;
white-space:nowrap;
vertical-align:baseline;
text-align:center;
cursor:pointer;
-webkit-user-drag:none;
-webkit-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none
}
.pure-button::-moz-focus-inner{
padding:0;
border:0
}
.pure-button{
font-family:inherit;
font-size:100%;
*font-size:90%;
*overflow:visible;
padding:.5em 1em;
color:#444;
color:rgba(0,0,0,.8);
*color:#444;
border:1px solid #999;
border:0 rgba(0,0,0,0);
background-color:#E6E6E6;
text-decoration:none;
border-radius:2px
}
.pure-button-hover,.pure-button:hover,.pure-button:focus{
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#1a000000', GradientType=0);
background-image:-webkit-gradient(linear,0 0,0 100%,from(transparent),color-stop(40%,rgba(0,0,0,.05)),to(rgba(0,0,0,.1)));
background-image:-webkit-linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1));
background-image:-moz-linear-gradient(top,rgba(0,0,0,.05) 0,rgba(0,0,0,.1));
background-image:-o-linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1));
background-image:linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1))
}
.pure-button:focus{
outline:0
}
.pure-button-active,.pure-button:active{
box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset
}
.pure-button[disabled],.pure-button-disabled,.pure-button-disabled:hover,.pure-button-disabled:focus,.pure-button-disabled:active{
border:0;
background-image:none;
filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);
filter:alpha(opacity=40);
-khtml-opacity:.4;
-moz-opacity:.4;
opacity:.4;
cursor:not-allowed;
box-shadow:none
}
.pure-button-hidden{
display:none
}
.pure-button::-moz-focus-inner{
padding:0;
border:0
}
.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{
background-color:#0078e7;
color:#fff
}
.pure-form input[type=text],.pure-form input[type=password],.pure-form input[type=email],.pure-form input[type=url],.pure-form input[type=date],.pure-form input[type=month],.pure-form input[type=time],.pure-form input[type=datetime],.pure-form input[type=datetime-local],.pure-form input[type=week],.pure-form input[type=number],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=color],.pure-form select,.pure-form textarea{
padding:.5em .6em;
display:inline-block;
border:1px solid #ccc;
box-shadow:inset 0 1px 3px #ddd;
border-radius:4px;
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box
}
.pure-form input:not([type]){
padding:.5em .6em;
display:inline-block;
border:1px solid #ccc;
box-shadow:inset 0 1px 3px #ddd;
border-radius:4px;
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box
}
.pure-form input[type=color]{
padding:.2em .5em
}
.pure-form input[type=text]:focus,.pure-form input[type=password]:focus,.pure-form input[type=email]:focus,.pure-form input[type=url]:focus,.pure-form input[type=date]:focus,.pure-form input[type=month]:focus,.pure-form input[type=time]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=week]:focus,.pure-form input[type=number]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=color]:focus,.pure-form select:focus,.pure-form textarea:focus{
outline:0;
outline:thin dotted \9;
border-color:#129FEA
}
.pure-form input:not([type]):focus{
outline:0;
outline:thin dotted \9;
border-color:#129FEA
}
.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus,.pure-form input[type=checkbox]:focus{
outline:thin dotted #333;
outline:1px auto #129FEA
}
.pure-form .pure-checkbox,.pure-form .pure-radio{
margin:.5em 0;
display:block
}
.pure-form input[type=text][disabled],.pure-form input[type=password][disabled],.pure-form input[type=email][disabled],.pure-form input[type=url][disabled],.pure-form input[type=date][disabled],.pure-form input[type=month][disabled],.pure-form input[type=time][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=week][disabled],.pure-form input[type=number][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=color][disabled],.pure-form select[disabled],.pure-form textarea[disabled]{
cursor:not-allowed;
background-color:#eaeded;
color:#cad2d3
}
.pure-form input:not([type])[disabled]{
cursor:not-allowed;
background-color:#eaeded;
color:#cad2d3
}
.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{
background:#eee;
color:#777;
border-color:#ccc
}
.pure-form input:focus:invalid,.pure-form textarea:focus:invalid,.pure-form select:focus:invalid{
color:#b94a48;
border-color:#ee5f5b
}
.pure-form input:focus:invalid:focus,.pure-form textarea:focus:invalid:focus,.pure-form select:focus:invalid:focus{
border-color:#e9322d
}
.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus,.pure-form input[type=checkbox]:focus:invalid:focus{
outline-color:#e9322d
}
.pure-form select{
border:1px solid #ccc;
background-color:#fff
}
.pure-form select[multiple]{
height:auto
}
.pure-form label{
margin:.5em 0 .2em
}
.pure-form fieldset{
margin:0;
padding:.35em 0 .75em;
border:0
}
.pure-form legend{
display:block;
width:100%;
padding:.3em 0;
margin-bottom:.3em;
color:#333;
border-bottom:1px solid #e5e5e5
}
.pure-form-stacked input[type=text],.pure-form-stacked input[type=password],.pure-form-stacked input[type=email],.pure-form-stacked input[type=url],.pure-form-stacked input[type=date],.pure-form-stacked input[type=month],.pure-form-stacked input[type=time],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=week],.pure-form-stacked input[type=number],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=color],.pure-form-stacked select,.pure-form-stacked label,.pure-form-stacked textarea{
display:block;
margin:.25em 0
}
.pure-form-stacked input:not([type]){
display:block;
margin:.25em 0
}
.pure-form-aligned input,.pure-form-aligned textarea,.pure-form-aligned select,.pure-form-aligned .pure-help-inline,.pure-form-message-inline{
display:inline-block;
*display:inline;
*zoom:1;
vertical-align:middle
}
.pure-form-aligned textarea{
vertical-align:top
}
.pure-form-aligned .pure-control-group{
margin-bottom:.5em
}
.pure-form-aligned .pure-control-group label{
text-align:right;
display:inline-block;
vertical-align:middle;
width:10em;
margin:0 1em 0 0
}
.pure-form-aligned .pure-controls{
margin:1.5em 0 0 10em
}
.pure-form input.pure-input-rounded,.pure-form .pure-input-rounded{
border-radius:2em;
padding:.5em 1em
}
.pure-form .pure-group fieldset{
margin-bottom:10px
}
.pure-form .pure-group input{
display:block;
padding:10px;
margin:0;
border-radius:0;
position:relative;
top:-1px
}
.pure-form .pure-group input:focus{
z-index:2
}
.pure-form .pure-group input:first-child{
top:1px;
border-radius:4px 4px 0 0
}
.pure-form .pure-group input:last-child{
top:-2px;
border-radius:0 0 4px 4px
}
.pure-form .pure-group button{
margin:.35em 0
}
.pure-form .pure-input-1{
width:100%
}
.pure-form .pure-input-2-3{
width:66%
}
.pure-form .pure-input-1-2{
width:50%
}
.pure-form .pure-input-1-3{
width:33%
}
.pure-form .pure-input-1-4{
width:25%
}
.pure-form .pure-help-inline,.pure-form-message-inline{
display:inline-block;
padding-left:.3em;
color:#666;
vertical-align:middle;
font-size:.875em
}
.pure-form-message{
display:block;
color:#666;
font-size:.875em
}
@media only screen and (max-width :480px){
.pure-form button[type=submit]{
margin:.7em 0 0
}
.pure-form input:not([type]),.pure-form input[type=text],.pure-form input[type=password],.pure-form input[type=email],.pure-form input[type=url],.pure-form input[type=date],.pure-form input[type=month],.pure-form input[type=time],.pure-form input[type=datetime],.pure-form input[type=datetime-local],.pure-form input[type=week],.pure-form input[type=number],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=color],.pure-form label{
margin-bottom:.3em;
display:block
}
.pure-group input:not([type]),.pure-group input[type=text],.pure-group input[type=password],.pure-group input[type=email],.pure-group input[type=url],.pure-group input[type=date],.pure-group input[type=month],.pure-group input[type=time],.pure-group input[type=datetime],.pure-group input[type=datetime-local],.pure-group input[type=week],.pure-group input[type=number],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=color]{
margin-bottom:0
}
.pure-form-aligned .pure-control-group label{
margin-bottom:.3em;
text-align:left;
display:block;
width:100%
}
.pure-form-aligned .pure-controls{
margin:1.5em 0 0
}
.pure-form .pure-help-inline,.pure-form-message-inline,.pure-form-message{
display:block;
font-size:.75em;
padding:.2em 0 .8em
}
}
.pure-menu ul{
position:absolute;
visibility:hidden
}
.pure-menu.pure-menu-open{
visibility:visible;
z-index:2;
width:100%
}
.pure-menu ul{
left:-10000px;
list-style:none;
margin:0;
padding:0;
top:-10000px;
z-index:1
}
.pure-menu>ul{
position:relative
}
.pure-menu-open>ul{
left:0;
top:0;
visibility:visible
}
.pure-menu-open>ul:focus{
outline:0
}
.pure-menu li{
position:relative
}
.pure-menu a,.pure-menu .pure-menu-heading{
display:block;
color:inherit;
line-height:1.5em;
padding:5px 20px;
text-decoration:none;
white-space:nowrap
}
.pure-menu.pure-menu-horizontal>.pure-menu-heading{
display:inline-block;
*display:inline;
zoom:1;
margin:0;
vertical-align:middle
}
.pure-menu.pure-menu-horizontal>ul{
display:inline-block;
*display:inline;
zoom:1;
vertical-align:middle
}
.pure-menu li a{
padding:5px 20px
}
.pure-menu-can-have-children>.pure-menu-label:after{
content:'\25B8';
float:right;
font-family:'Lucida Grande','Lucida Sans Unicode','DejaVu Sans',sans-serif;
margin-right:-20px;
margin-top:-1px
}
.pure-menu-can-have-children>.pure-menu-label{
padding-right:30px
}
.pure-menu-separator{
background-color:#dfdfdf;
display:block;
height:1px;
font-size:0;
margin:7px 2px;
overflow:hidden
}
.pure-menu-hidden{
display:none
}
.pure-menu-fixed{
position:fixed;
top:0;
left:0;
width:100%
}
.pure-menu-horizontal li{
display:inline-block;
*display:inline;
zoom:1;
vertical-align:middle
}
.pure-menu-horizontal li li{
display:block
}
.pure-menu-horizontal>.pure-menu-children>.pure-menu-can-have-children>.pure-menu-label:after{
content:"\25BE"
}
.pure-menu-horizontal>.pure-menu-children>.pure-menu-can-have-children>.pure-menu-label{
padding-right:30px
}
.pure-menu-horizontal li.pure-menu-separator{
height:50%;
width:1px;
margin:0 7px
}
.pure-menu-horizontal li li.pure-menu-separator{
height:1px;
width:auto;
margin:7px 2px
}
.pure-menu.pure-menu-open,.pure-menu.pure-menu-horizontal li .pure-menu-children{
background:#fff;
border:1px solid #b7b7b7
}
.pure-menu.pure-menu-horizontal,.pure-menu.pure-menu-horizontal .pure-menu-heading{
border:0
}
.pure-menu a{
border:1px solid transparent;
border-left:0;
border-right:0
}
.pure-menu a,.pure-menu .pure-menu-can-have-children>li:after{
color:#777
}
.pure-menu .pure-menu-can-have-children>li:hover:after{
color:#fff
}
.pure-menu .pure-menu-open{
background:#dedede
}
.pure-menu li a:hover,.pure-menu li a:focus{
background:#eee
}
.pure-menu li.pure-menu-disabled a:hover,.pure-menu li.pure-menu-disabled a:focus{
background:#fff;
color:#bfbfbf
}
.pure-menu .pure-menu-disabled>a{
background-image:none;
border-color:transparent;
cursor:default
}
.pure-menu .pure-menu-disabled>a,.pure-menu .pure-menu-can-have-children.pure-menu-disabled>a:after{
color:#bfbfbf
}
.pure-menu .pure-menu-heading{
color:#565d64;
text-transform:uppercase;
font-size:90%;
margin-top:.5em;
border-bottom-width:1px;
border-bottom-style:solid;
border-bottom-color:#dfdfdf
}
.pure-menu .pure-menu-selected a{
color:#000
}
.pure-menu.pure-menu-open.pure-menu-fixed{
border:0;
border-bottom:1px solid #b7b7b7
}
.pure-paginator{
letter-spacing:-.31em;
*letter-spacing:normal;
*word-spacing:-.43em;
text-rendering:optimizespeed;
list-style:none;
margin:0;
padding:0
}
.opera-only :-o-prefocus,.pure-paginator{
word-spacing:-.43em
}
.pure-paginator li{
display:inline-block;
*display:inline;
zoom:1;
letter-spacing:normal;
word-spacing:normal;
vertical-align:top;
text-rendering:auto
}
.pure-paginator .pure-button{
border-radius:0;
padding:.8em 1.4em;
vertical-align:top;
height:1.1em
}
.pure-paginator .pure-button:focus,.pure-paginator .pure-button:active{
outline-style:none
}
.pure-paginator .prev,.pure-paginator .next{
color:#C0C1C3;
text-shadow:0 -1px 0 rgba(0,0,0,.45)
}
.pure-paginator .prev{
border-radius:2px 0 0 2px
}
.pure-paginator .next{
border-radius:0 2px 2px 0
}
@media (max-width:480px){
.pure-menu-horizontal{
width:100%
}
.pure-menu-children li{
display:block;
border-bottom:1px solid #000
}
}
.pure-table{
border-collapse:collapse;
border-spacing:0;
empty-cells:show;
border:1px solid #cbcbcb
}
.pure-table caption{
color:#000;
font:italic 85%/1 arial,sans-serif;
padding:1em 0;
text-align:center
}
.pure-table td,.pure-table th{
border-left:1px solid #cbcbcb;
border-width:0 0 0 1px;
font-size:inherit;
margin:0;
overflow:visible;
padding:.5em 1em
}
.pure-table td:first-child,.pure-table th:first-child{
border-left-width:0
}
.pure-table thead{
background:#e0e0e0;
color:#000;
text-align:left;
vertical-align:bottom
}
.pure-table td{
background-color:transparent
}
.pure-table-odd td{
background-color:#f2f2f2
}
.pure-table-striped tr:nth-child(2n-1) td{
background-color:#f2f2f2
}
.pure-table-bordered td{
border-bottom:1px solid #cbcbcb
}
.pure-table-bordered tbody>tr:last-child td,.pure-table-horizontal tbody>tr:last-child td{
border-bottom-width:0
}
.pure-table-horizontal td,.pure-table-horizontal th{
border-width:0 0 1px;
border-bottom:1px solid #cbcbcb
}
.pure-table-horizontal tbody>tr:last-child td{
border-bottom-width:0
}

View File

@ -0,0 +1,276 @@
body {
/* color: #777; */
}
.pure-img-responsive {
max-width: 100%;
height: auto;
}
/*
Add transition to containers so they can push in and out.
*/
#layout,
#menu,
.menu-link {
-webkit-transition: all 0.2s ease-out;
-moz-transition: all 0.2s ease-out;
-ms-transition: all 0.2s ease-out;
-o-transition: all 0.2s ease-out;
transition: all 0.2s ease-out;
}
/*
This is the parent `<div>` that contains the menu and the content area.
*/
#layout {
position: relative;
padding-left: 0;
}
#layout.active {
position: relative;
left: 200px;
}
#layout.active #menu {
left: 200px;
width: 200px;
}
#layout.active .menu-link {
left: 200px;
}
/*
The content `<div>` is where all your content goes.
*/
.content {
margin: 0 auto;
padding: 0 2em;
max-width: 800px;
margin-bottom: 50px;
line-height: 1.6em;
color: #444;
}
.header {
margin: 0;
color: #333;
text-align: center;
padding: 2.5em 2em 0;
border-bottom: 1px solid #eee;
}
.header h1 {
margin: 0.2em 0;
font-size: 3em;
font-weight: 300;
}
.header h2 {
font-weight: 300;
color: #ccc;
padding: 0;
margin-top: 0;
}
.content-subhead {
margin: 50px 0 20px 0;
font-weight: 300;
color: #888;
}
#inout {
padding: 1em;
}
.blockhead {
display: block;
height: 1em;
}
.wanmarker {
background: #77c;
padding: 0.25em;
color: #fff;
}
.lanmarker {
background: #cc7;
padding: 0.25em;
color: #fff;
}
.wlanmarker {
background: #7c7;
padding: 0.25em;
color: #fff;
}
.ffmarker {
background: #ffc12e;
padding: 0.25em;
color: #fff;
}
.infotext {
font-size: 0.8em;
padding-right: 1em;
}
/*
The `#menu` `<div>` is the parent `<div>` that contains the `.pure-menu` that
appears on the left side of the page.
*/
#menu {
margin-left: -200px; /* "#menu" width */
width: 200px;
position: fixed;
top: 0;
left: 0;
bottom: 0;
z-index: 1000; /* so the menu or its navicon stays above all content */
background: #191818;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
/*
All anchors inside the menu should be styled like this.
*/
#menu a {
color: #aaa;
border: none;
padding: 0.6em 0 0.6em 0.6em;
}
/*
Remove all background/borders, since we are applying them to #menu.
*/
#menu .pure-menu,
#menu .pure-menu ul {
border: none;
background: transparent;
}
/*
Add that light border to separate items into groups.
*/
#menu .pure-menu ul,
#menu .pure-menu .menu-item-divided {
border-top: 1px solid #333;
}
/*
Change color of the anchor links on hover/focus.
*/
#menu .pure-menu li a:hover,
#menu .pure-menu li a:focus {
background: #dc0067;
color: #ffffff;
}
/*
This styles the selected menu item `<li>`.
*/
#menu .pure-menu-selected {
background: #ffc12e;
color: #fff;
}
/*
This styles a link within a selected menu item `<li>`.
*/
#menu .pure-menu-selected a {
color: #fff;
}
/*
This styles the menu heading.
*/
#menu .pure-menu-heading {
font-size: 110%;
color: #fff;
margin: 0;
}
/* -- Dynamic Button For Responsive Menu -------------------------------------*/
/*
The button to open/close the Menu is custom-made and not part of Pure. Here's
how it works:
*/
/*
`.menu-link` represents the responsive menu toggle that shows/hides on
small screens.
*/
.menu-link {
position: fixed;
display: block; /* show this only on small screens */
top: 0;
left: 0; /* "#menu width" */
background: #000;
background: rgba(0,0,0,0.7);
font-size: 10px; /* change this value to increase/decrease button size */
z-index: 10;
width: 2em;
height: auto;
padding: 2.1em 1.6em;
}
.menu-link:hover,
.menu-link:focus {
background: #000;
}
.menu-link span {
position: relative;
display: block;
}
.menu-link span,
.menu-link span:before,
.menu-link span:after {
background-color: #fff;
width: 100%;
height: 0.2em;
}
.menu-link span:before,
.menu-link span:after {
position: absolute;
margin-top: -0.6em;
content: " ";
}
.menu-link span:after {
margin-top: 0.6em;
}
/* -- Responsive Styles (Media Queries) ------------------------------------- */
/*
Hides the menu at `48em`, but modify this based on your app's needs.
*/
@media (min-width: 48em) {
.header,
.content {
padding-left: 2em;
padding-right: 2em;
}
#layout {
padding-left: 200px; /* left col width "#menu" */
left: 0;
}
#menu {
left: 200px;
}
.menu-link {
position: fixed;
left: 200px;
display: none;
}
#layout.active .menu-link {
left: 200px;
}
}

View File

@ -0,0 +1,78 @@
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
body {
line-height: 1.7em;
color: #7f8c8d;
font-size: 13px;
}
h1,
h2,
h3,
h4,
h5,
h6,
label {
color: #34495e;
}
.pure-img-responsive {
max-width: 100%;
height: auto;
}
.pure-button {
background-color: #1f8dd6;
color: white;
padding: 0.5em 2em;
border-radius: 5px;
}
a.pure-button-primary {
background: white;
color: #1f8dd6;
border-radius: 5px;
font-size: 120%;
}
.home-menu {
padding: 0.5em;
text-align: center;
box-shadow: 0 1px 1px rgba(0,0,0, 0.10);
}
.home-menu.pure-menu-open {
background: #2d3e50;
}
.home-menu .pure-menu-heading {
color: white;
font-weight: 400;
font-size: 120%;
}
.home-menu .pure-menu-selected a {
color: white;
}
.home-menu a {
color: #6FBEF3;
}
.home-menu li a:hover,
.home-menu li a:focus {
background: none;
color: #AECFE5;
}
.home-menu {
text-align: left;
}
.home-menu ul {
float: right;
}

View File

@ -0,0 +1,13 @@
<html>
<head>
<meta charset="utf-8"/>
<meta http-equiv="refresh" content="0; URL=/cgi-bin/status">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT">
<meta http-equiv="pragma" content="no-cache">
</head>
<body>
<a href="/cgi-bin/status">Redirecting...</a>
</body>
</html>

View File

@ -0,0 +1,71 @@
#!/usr/bin/haserl
<%
echo -en "content-type: text/plain\r\n\r\n"
addr() {
local addr="$(ip -$1 address show dev $2 2> /dev/null | tr '/' ' '| awk '/inet/{ printf("%s ", $2); }')"
echo "${addr:--}"
}
default_gw() {
ip -$1 route list 0/0 dev $2 2> /dev/null | awk '{print($3); exit(0)}'
}
print() {
echo " option $1 '$2'"
}
printList() {
for item in $2; do
echo " list $1 '$item'"
done
}
#include OpenWrt version
. /etc/openwrt_release
. /etc/firmware_release
echo "package misc"
echo "config data 'data'"
print 'mac' "$(uci -q get network.mesh.macaddr)"
wanif=$(uci -q get network.wan.ifname)
printList 'freifunk_addr4' "$(addr 4 br-mesh)"
printList 'freifunk_addr6' "$(addr 6 br-mesh)"
printList 'wan_addr4' "$(addr 4 $wanif)"
printList 'wan_addr6' "$(addr 6 $wanif)"
up="$(uptime)"
print 'load' "${up##*:}"
uptime="${up%%,*}"
print 'uptime' "${uptime##*up}"
print 'uname' "$(uname -s -m -r)"
print 'date' "$(date)"
if [ $(sockread /var/run/fastd.status < /dev/null 2> /dev/null | grep -c '"connection": {') -gt 0 ]; then
print 'has_vpn' 'Ja'
else
print 'has_vpn' 'Nein'
fi
if [ -n "$(default_gw 4 $wanif)" -o -n "$(default_gw 6 $wanif)" ]; then
print 'has_internet' 'Ja'
else
print 'has_internet' 'Nein'
fi
print 'node_count' "$((`cat /sys/kernel/debug/batman_adv/bat0/transtable_global | grep '^ [^ ]' | cut -b 39-55 | sort | uniq | wc -l 2> /dev/null`+1))"
print 'neigh_count' "$(cat /sys/kernel/debug/batman_adv/bat0/originators | grep '^[0-9a-f]' | cut -b 37-53 | sort | uniq | wc -l 2> /dev/null)"
print 'firmware_version' "$FIRMWARE_VERSION"
print 'fastd_version' "$(fastd --version 2> /dev/null | cut -d' ' -f 2)"
print 'batman_version' "$(cat /sys/module/batman_adv/version 2> /dev/null)"
print 'openwrt_version' "$DISTRIB_DESCRIPTION"
name="$(uci get -q 'system.@system[0].hostname')"
print 'name' "${name:--}"
print 'model' "$(cat /tmp/sysinfo/model 2> /dev/null)"
print 'freifunk_user_count' "$(cat /sys/kernel/debug/batman_adv/bat0/transtable_local 2> /dev/null | grep -c 'W')"
print 'freifunk_rx_bytes' "$(cat /sys/class/net/br-mesh/statistics/rx_bytes 2> /dev/null)"
print 'freifunk_tx_bytes' "$(cat /sys/class/net/br-mesh/statistics/tx_bytes 2> /dev/null)"
print 'wan_rx_bytes' "$(cat /sys/class/net/$wanif/statistics/rx_bytes 2> /dev/null)"
print 'wan_tx_bytes' "$(cat /sys/class/net/$wanif/statistics/tx_bytes 2> /dev/null)"
%>

View File

@ -0,0 +1,33 @@
#!/usr/bin/haserl
<%
echo -en "content-type: text/plain\r\n\r\n"
case $GET_func in
reboot)
reboot
echo "(I) Bitte warten. Neustart wird durchgef&#252;hrt..."
;;
wifi_status)
wifi status
;;
wifiscan)
iw dev "$GET_device" scan 2> /dev/null | grep '^BSS \|SSID\|set: channel\|signal\|capability\|MESH ID'
;;
set_config_file)
file_name="$GET_name"
file_data="$GET_data"
if echo "$file_data" > "/etc/config/$file_name" 2> /dev/null; then
echo "(I) Einstellungen wurden gespeichert. Bitte Neustarten."
if [ "$file_name" = "system" ]; then
uci get -q 'system.@system[0].hostname' > /proc/sys/kernel/hostname
fi
else
echo "(E) Beim Speichern ist ein Fehler aufgetreten. Bitte Neustarten."
fi
;;
*)
echo "(E) misc: Invalid command: '$GET_func'"
;;
esac
%>

View File

@ -0,0 +1,16 @@
#!/usr/bin/haserl
<%
echo -en "content-type: text/plain\r\n\r\n"
pass1="$GET_pass1"
pass2="$GET_pass2"
(echo "$pass1"; sleep 1; echo "$pass2") | passwd &> /dev/null
if [ $? -eq 0 ]; then
#force instant password change
/etc/init.d/uhttpd restart 2> /dev/null
else
echo "(E) Es ist ein Fehler aufgetreten."
fi
%>

View File

@ -0,0 +1,16 @@
#!/usr/bin/haserl
<%
echo -en "content-type: text/plain\r\n\r\n"
. /lib/functions.sh
case "$GET_func" in
get_settings)
uci export -qn system
uci export -qn simple-tc
;;
*)
echo "(E) settings: Invalid command: '$GET_func'"
;;
esac
%>

View File

@ -0,0 +1,36 @@
#!/usr/bin/haserl --upload-dir=/tmp --upload-limit=12000
<%
echo -en "content-type: text/plain\r\n\r\n"
case "${GET_func:-$POST_func}" in
apply_firmware)
path="$POST_firmware"
keep="$POST_keep_config"
if [ ! -f "$path" ]; then
echo "(E) Datei nicht gefunden."
exit 1
fi
if [ "$keep" = "yes" ]; then
args=""
else
args="-n"
fi
echo "(I) Starte sysupgrade..."
#apply openwrt or vendor image
sysupgrade $args $path
;;
restore_firmware)
echo "(I) Undo all changes ..."
echo y | firstboot
echo "(I) Rebooting now ..."
reboot
;;
*)
echo "(E) upgrade: Invalid command: '$GET_func'"
;;
esac
%>

View File

@ -0,0 +1,54 @@
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="style.css" />
<script src="shared.js"></script>
<script src="home.js"></script>
</head>
<body onload="init();">
<fieldset>
<legend id="system">System</legend>
<div><label>Name: </label><span id="name">?</span></div>
<div><label>Modell: </label><span id="model">?</span></div>
<div><label>MAC-Adresse: </label><span id="mac">?</span></div>
<div><label>Bekannte Knoten: </label><span id="node_count">?</span></div>
<div><label>Nachbarknoten: </label><span id="neigh_count">?</span></div>
<div><label>VPN aktiv: </label><span id="has_vpn">?</span></div>
<div><label>Laufzeit: </label><span id="uptime">?</span></div>
<div><label>Auslastung: </label><span id="load">?</span></div>
<div><label>System: </label><span id="uname">?</span></div>
<div><label>Uhrzeit: </label><span id="date">?</span></div>
</fieldset>
<fieldset>
<legend id="freifunk">Netz: Freifunk</legend>
<div><label>Nutzer: </label><span id="freifunk_user_count">?</span></div>
<div><label>Empfangen: </label><span id="freifunk_rx_bytes">?</span> </div>
<div><label>Gesendet: </label><span id="freifunk_tx_bytes">?</span></div>
<div><label>IPv4 Adressen: </label><span id="freifunk_addr4">?</span></div>
<div><label>IPv6 Adressen: </label><span id="freifunk_addr6">?</span></div>
</fieldset>
<fieldset>
<legend id="wan">Netz: WAN</legend>
<div><label>Internet Vorhanden: </label><span id="has_internet">?</span></div>
<div><label>Empfangen: </label><span id="wan_rx_bytes">?</span> </div>
<div><label>Gesendet: </label><span id="wan_tx_bytes">?</span></div>
<div><label>IPv4 Adressen: </label><span id="wan_addr4">?</span></div>
<div><label>IPv6 Adressen: </label><span id="wan_addr6">?</span></div>
</fieldset>
<fieldset>
<legend id="software">Software</legend>
<div><label>Firmware Version: </label><span id="firmware_version">?</span></div>
<div><label>OpenWrt Version: </label><span id="openwrt_version">?</span></div>
<div><label>Batman-Adv Version: </label><span id="batman_version">?</span></div>
<div><label>Fastd Version: </label><span id="fastd_version">?</span></div>
</fieldset>
</body>
</html>

View File

@ -0,0 +1,46 @@
function formatSize(bytes) {
if(typeof bytes === "undefined" || bytes == "") {
return "-";
} else if (bytes < 1000) {
return bytes + " B";
} else if (bytes < 1000*1000) {
return (bytes/ 1000.0).toFixed(0) + " KB";
} else if (bytes < 1000*1000*1000) {
return (bytes/1000.0/1000.0).toFixed(1) + " MB";
} else {
return (bytes/1000.0/1000.0/1000.0).toFixed(2) + " GB";
}
}
function init() {
send("/cgi-bin/home", { }, function(data) {
var obj = fromUCI(data).misc.data;
for(var key in obj) {
var value = obj[key];
if(key == 'stype') {
continue;
}
//for traffic
if(/_bytes$/.test(key)) {
value = formatSize(value);
}
//for addresses
if(typeof(value) == 'object') {
value = "<ul><li>"+value.join("</li><li>")+"</li></ul>"
}
setText(key, value);
}
});
addHelpText($("system"), "Eine \xdcbersicht \xfcber den Router.");
addHelpText($("freifunk"), "Das \xf6ffentliche Freifunknetz..");
addHelpText($("wan"), "Das Netz \xfcber dass das Internet erreicht wird.");
addHelpText($("software"), "Einige installierte Softwareversionen.");
addHelpText($("freifunk_user_count"), "Die Anzahl der Nutzer an diesem Router in den letzten zwei Stunden.");
addHelpText($("has_vpn"), "Status der VPN-Verbindung zum Server im Internet.");
}

View File

@ -0,0 +1,124 @@
<!DOCTYPE html>
<html>
<head>
<title>Freifunk</title>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="style.css" />
<script src="shared.js"></script>
<script type="text/javascript">
var html_cache = {};
var js_cache = {};
var adv_mode = false;
function adv_apply()
{
var inputs = document.getElementsByClassName('adv_disable');
var elems = document.getElementsByClassName('adv_hide');
for(var i=0; i < inputs.length; i++)
inputs[i].disabled = adv_mode ? "": "disabled";
for(var i=0; i < elems.length; i++)
elems[i].style.display = adv_mode ? "block" : "none";
}
function adv_toggle(e)
{
adv_mode = !adv_mode;
e.innerHTML = adv_mode ? "Erweitert: An" : "Erweitert: Aus";
adv_apply();
}
function nav_onclick()
{
setText('msg', "");
var url = this.getAttribute("href");
if(url == '#') return false;
var id = url.substring(0, url.lastIndexOf('.'));
var process_html = function(data) {
var b = $("body");
removeChilds(b);
var pattern = /<body[^>]*>((.|[\n\r])*)<\/body>/im;
b.innerHTML = pattern.exec(data)[1];
html_cache[id] = data;
};
var process_js = function(data) {
(window.execScript || function(data) {
window["eval"].call(window, data);
window["eval"].call(window, "init();");
})(data);
js_cache[id] = data;
};
//load html file
if(id in html_cache)
process_html(html_cache[id]);
else
jx.load(url, process_html, 'text');
//load javascript file
if(id in js_cache)
process_js(js_cache[id]);
else
jx.load(url.replace(".html", ".js"), process_js, 'text');
onDesc($("globalnav"), 'UL', function(n) { hide(n); });
onParents(this, 'UL', function(n) { show(n); });
onChilds(this.parentNode, 'UL', function(n) { show(n); });
onDesc($("globalnav"), 'A', function(n) { removeClass(n, "here"); });
onParents(this, 'LI', function(n) { addClass(n.firstChild, "here"); });
return false;
}
function preselect() {
onDesc($("globalnav"), 'UL', function(n) { hide(n); });
onDesc($("globalnav"), 'A', function(n) {
if(n.getAttribute("href") != '#')
n.onclick = nav_onclick;
});
$("first").onclick();
}
function reboot() {
if(!confirm("Neustart durchf\xFChren?")) return;
send("/cgi-bin/misc", { func : "reboot" }, function(data) {
setText('msg', data);
});
}
function logout() {
window.location="https://none@" + window.location.host;
}
</script>
</head>
<body onload="preselect();">
<ul id="globalnav">
<li><a href="home.html" id="first">Home</a></li>
<li><a href="settings.html">Einstellungen</a></li>
<li><a href="wifiscan.html">WifiScan</a></li>
<li><a href="upgrade.html">Upgrade</a></li>
<li><a href="password.html">Password</a></li>
<li><a href="#" onclick="reboot()">Neustart</a></li>
<li><a href="#" onclick="logout()">Logout</a></li>
<li><a href="#" onclick="adv_toggle(this)">Erweitert: Aus</a></li>
</ul>
<br>
<pre id="msg" tabindex="-1"></pre>
<div id="help"></div>
<div id="body"></div>
<div id="footer"></div>
</body>
</html>

View File

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<title>Password</title>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="style.css" />
<script src="shared.js"></script>
<script src="password.js"></script>
</head>
<body onload="init();">
<fieldset>
<legend>Passwort</legend>
<div>
<label>Neues Password:</label> <input id="p1" type="password">
</div>
<div>
<label>Bestätigung:</label> <input id="p2" type="password">
</div>
<div><br />Das Passwort ist für den Zugriff auf die Weboberfläche des Routers und auch den Zugriff per SSH. Der Benutzername ist 'root'.</div>
</fieldset>
<div>
<button type="button" onclick="apply()">&Auml;ndern</button>
</div>
</body>
</html>

View File

@ -0,0 +1,24 @@
function init() {
$("p1").focus();
}
function apply()
{
p1 = $('p1').value;
p2 = $('p2').value;
$('p1').value = "";
$('p2').value = "";
if(p1 != p2) {
setText('msg', "(E) Die Passw&ouml;rter sind nicht identisch.");
return;
} else {
setText('msg', "(I) Das Passwort wird ge&auml;ndert. Bitte die Seite neu laden.");
}
send("/cgi-bin/password", { func : "set_password", pass1 : p1, pass2 : p2 }, function(data) {
setText('msg', data);
});
}

View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<title>Einstellungen</title>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="style.css" />
<script src="shared.js"></script>
<script src="settings.js"></script>
</head>
<body onload="init();">
<fieldset>
<legend>Allgemeine Einstellungen</legend>
<span id="general"></span>
</fieldset>
<fieldset>
<legend>Bandbreitenkontrolle</legend>
<span id="traffic"></span>
<div><br />Die f&#252;r das Freifunknetz beanspruchte Internet-Bandbreite am WAN kann hier begrenzt werden.</div>
</fieldset>
<button type="button" onclick="save_data()">Speichern</button>
</body>
</html>

View File

@ -0,0 +1,142 @@
/*
All required uci packages are stored variable uci.
The GUI code displayes and manipulated this variable.
*/
var uci = {};
var gid = 0;
function init()
{
send("/cgi-bin/settings", { func : "get_settings" }, function(data) {
uci = fromUCI(data);
rebuild_general();
adv_apply();
});
}
function updateFrom(src)
{
var obj = {};
collect_inputs(src, obj);
for(var name in obj)
{
var value = obj[name];
var path = name.split('#');
var pkg = path[0];
var sec = path[1];
var opt = path[2];
uci[pkg].pchanged = true;
uci[pkg][sec][opt] = value;
}
}
function getChangeModeAction(ifname)
{
return function(e) {
var src = (e.target || e.srcElement);
var mode = (src.data || src.value);
delNetSection(ifname);
addNetSection(ifname, mode);
};
}
function appendSetting(p, path, value, mode)
{
var id = path.join('#');
var b;
var cfg = path[0];
var name = path[path.length-1];
switch(name)
{
case "geo":
b = append_input(p, "GPS-Koordinaten", id, value);
b.lastChild.placeholder = "52.02713078 8.52829987";
addInputCheck(b.lastChild, /^$|^\d{1,3}\.\d{1,8} {1,3}\d{1,3}\.\d{1,8}$/, "Ung\xfcltige Eingabe. Bitte nur maximal 8 Nachkommastellen und keine Kommas verwenden.");
addHelpText(b, "Die Koordinaten dieses Knotens auf der Freifunk-Karte (z.B. \"52.02713078 8.52829987\").");
break;
case "hostname":
b = append_input(p, "Knotenname", id, value);
b.lastChild.placeholder = "MeinRouter";
addInputCheck(b.lastChild, /^$|^[\-\^'\w\.\:\[\]\(\)\/ &@\+\u0080-\u00FF]{0,32}$/, "Ung\xfcltige Eingabe.");
addHelpText(b, "Der Name dieses Knotens auf der Freifunk-Karte.");
break;
case "contact":
b = append_input(p, "Kontaktdaten", id, value);
b.lastChild.placeholder = "info@example.com";
addInputCheck(b.lastChild, /^$|^[\-\^'\w\.\:\[\]\(\)\/ &@\+\u0080-\u00FF]{0,32}$/, "Ung\xfcltige Eingabe.");
addHelpText(b, "Kontaktdaten f\xfcr die \xf6ffentliche Freifunk-Karte und Statusseite. Falls ihr euch von anderen Leuten kontaktieren lassen wollt (z.B. \"info@example.com\").");
break;
case "enabled":
if(cfg == "simple-tc") {
b = append_radio(p, "Bandbreitenkontrolle", id, value, [["An", "1"], ["Aus", "0"]]);
addHelpText(b, "Bandbreitenkontrolle f\xfcr den Upload-/Download \xfcber das Freifunknetz \xfcber den eigenen Internetanschluss.");
}
break;
case "limit_egress":
b = append_input(p, "Freifunk Upload", id, value);
addInputCheck(b.lastChild, /^\d+$/, "Upload ist ung\xfcltig.");
addHelpText(b, "Maximaler Upload in KBit/s f\xfcr die Bandbreitenkontrolle.");
break;
case "limit_ingress":
b = append_input(p, "Freifunk Download", id, value);
addInputCheck(b.lastChild, /^\d+$/, "Download ist ung\xfcltig.");
addHelpText(b, "Maximaler Download in KBit/s f\xfcr die Bandbreitenkontrolle.");
break;
default:
return;
}
b.id = id; //needed for updateFrom
b.onchange = function() {
updateFrom(b);
};
return b;
}
function rebuild_general()
{
var gfs = $("general");
var tfs = $("traffic");
removeChilds(gfs);
removeChilds(tfs);
if('system' in uci) {
var f = uci['system'];
var i = firstSectionID(f, "system");
appendSetting(gfs, ['system', i, "hostname"], f[i]["hostname"]);
appendSetting(gfs, ['system', i, "geo"], f[i]["geo"]);
appendSetting(gfs, ['system', i, "contact"], f[i]["contact"]);
}
if('simple-tc' in uci) {
var t = uci['simple-tc'];
var i = firstSectionID(t, "interface");
appendSetting(tfs, ['simple-tc', i, "enabled"], t[i]["enabled"]);
appendSetting(tfs, ['simple-tc', i, "limit_ingress"], t[i]["limit_ingress"]);
appendSetting(tfs, ['simple-tc', i, "limit_egress"], t[i]["limit_egress"]);
}
}
function save_data()
{
for(var name in uci)
{
var obj = uci[name];
if(!obj.pchanged)
continue;
var data = toUCI(obj);
send("/cgi-bin/misc", { func : "set_config_file", name : name, data : data },
function(data) {
$('msg').innerHTML = data;
$('msg').focus();
init();
}
);
}
}

View File

@ -0,0 +1,432 @@
function $(id) { return document.getElementById(id); }
function create(name) { return document.createElement(name); }
function show(e) { e.style.display='block'; }
function hide(e) { e.style.display='none'; }
function addClass(e, c) { e.classList.add(c); } //HTML5!
function removeClass(e, c) { e.classList.remove(c); }
function setText(id, txt) { $(id).innerHTML = txt; }
function inArray(item, array) { return array.indexOf(item) != -1; }
function split(str)
{
if(typeof str != 'string')
return [];
var a = str.match(/[^\s]+/g);
return (a ? a : []);
}
function uniq(arr)
{
var obj = {};
for(var i in arr) obj[arr[i]] = 0;
return Object.keys(obj);
}
//remove an item from a string list
function removeItem(str, item)
{
var array = split(str);
for(var i in array)
if(array[i] == item)
array.splice(i, 1);
return array.join(' ');
}
function addItem(str, item)
{
var array = split(str);
for(var i in array)
if(array[i] == item)
return str;
array.push(item);
return array.join(' ');
}
function replaceItem(str, old_item, new_item)
{
var array = split(str);
for(var i in array)
if(array[i] == old_item)
array[i] = new_item;
return array.join(' ');
}
function addHelpText(elem, text) {
var help = $("help");
if(help) {
elem.onmouseover = function(e) {
help.style.top = (e.clientY-20)+"px";
help.style.left = (e.clientX+80)+"px";
help.innerHTML = text;
show(help);
};
elem.onmouseout = function() {
help.innerHTML = "";
hide(help);
};
}
}
//to config file syntax
function toUCI(pkg_obj)
{
var str = "\n";
for(var sid in pkg_obj)
{
if(sid == "pchanged")
continue;
var options = pkg_obj[sid];
var sname = (sid.substring(0, 3) != "cfg") ? (" '"+sid+"'") : "";
str += "config "+options.stype+sname+"\n";
for(var oname in options)
{
if(oname == "stype")
continue;
var value = options[oname];
if(typeof value == 'object')
{
for(var i in value)
str += " list "+oname+" '"+value[i]+"'\n";
}
else
str += " option "+oname+" '"+value+"'\n";
}
str += "\n";
}
return str;
}
// parses output from one or multiple
// calls like "uci export -qn foo"
function fromUCI(pkgs_str)
{
var pkg_objs = {};
var pkg;
var cfg;
var lines = pkgs_str.split("\n");
for(var i = 0; i < lines.length; ++i)
{
var line = lines[i];
var items = split(line);
if(items.length < 2) continue;
switch(items[0])
{
case 'package':
pkg = { pchanged : false };
pkg_objs[items[1]] = pkg;
break;
case 'config':
var val = (items.length == 3) ? line.match(/'(.*)'/)[1] : ("cfg"+(++gid));
cfg = { stype : items[1] };
pkg[val] = cfg;
break;
case 'option':
var val = line.match(/'(.*)'/)[1];
cfg[items[1]] = val;
break;
case 'list':
var val = line.match(/'(.*)'/)[1];
if(!(items[1] in cfg)) cfg[items[1]] = [];
cfg[items[1]].push(val);
break;
}
}
return pkg_objs;
}
function firstSectionID(obj, stype)
{
for(var id in obj)
if(obj[id].stype == stype)
return id;
}
function config_foreach(objs, stype, func)
{
for(var key in objs)
{
var obj = objs[key];
if((obj["stype"] == stype || stype == "*") && func(key, obj))
return;
}
}
function config_find(objs, mobj)
{
for(var key in objs)
{
var obj = objs[key];
var found = true;
for(mkey in mobj)
{
if(obj[mkey] != mobj[mkey])
{
found = false;
break;
}
}
if(found)
return obj;
}
return null;
}
function params(obj)
{
var str = "";
for(var key in obj) {
if(str.length) str += "&";
else str += "?";
str += encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]);
}
return str.replace(/%20/g, "+");
}
function send(url, obj, func)
{
url += params(obj);
jx.load(url, func, 'text');
}
function onDesc(e, tag, func)
{
for(var i = 0; i < e.childNodes.length; ++i) {
var c = e.childNodes[i];
if(c.tagName == tag && func(c) == false) return;
onDesc(c, tag, func);
}
}
function onChilds(e, tag, func)
{
for(var i = 0; i < e.childNodes.length; ++i) {
var c = e.childNodes[i];
if(c.tagName == tag && func(c) == false) return;
}
}
function onParents(e, tag, func)
{
while(e != document) {
e = e.parentNode;
if(e.tagName == tag && func(e) == false) return;
}
}
function removeChilds(p)
{
while(p.hasChildNodes())
p.removeChild(p.firstChild);
}
function show_error(data)
{
var is_error = (data.substr(0, 3) == "(E)");
if(is_error)
setText('msg', data);
return is_error;
}
function checkName(name)
{
if(/[\w_]{2,12}/.test(name))
return true;
alert("Name '"+name+"' ist ung\xfcltig.");
return false;
}
//prepend input check
function addInputCheck(input, regex, msg)
{
var prev_value = input.value;
var prev_onchange = input.onchange;
input.onchange = function(e) {
if(regex.test(input.value)) {
if(prev_onchange)
prev_onchange(e);
return;
}
alert(msg);
input.value = prev_value;
e.stopPropagation();
};
}
function collect_inputs(p, obj)
{
if(p.tagName == "SELECT")
obj[p.name] = p.value;
if(p.tagName == "INPUT")
if(p.type == "text" || p.type == "password" || (p.type == "radio" && p.checked))
obj[p.name] = p.value
else if(p.type == "checkbox" && p.checked)
{
var v = obj[p.name];
v = (typeof v == "undefined") ? (p.data || p.value) : (v + " " + (p.data || p.value));
obj[p.name] = v;
}
for(var i = 0; i < p.childNodes.length; ++i)
collect_inputs(p.childNodes[i], obj);
}
function append(parent, tag, id)
{
var e = create(tag);
if(id) e.id = id;
parent.appendChild(e);
return e;
}
function append_section(parent, title, id)
{
var fs = append(parent, "fieldset");
var lg = create("legend");
lg.innerHTML = title;
if(id) fs.id = id;
fs.appendChild(lg);
return fs;
}
function append_button(parent, text, onclick)
{
var button = append(parent, 'button');
button.type = 'button';
button.innerHTML = text;
button.onclick = onclick;
return button;
}
function append_label(parent, title, value)
{
var div = append(parent, 'div');
var label = append(div, 'label');
label.innerHTML = title + ":";
if(typeof value == 'string')
{
//div.className = "label_option";
var span = append(div, 'span');
span.innerHTML = value;
}
else
{
div.className = "list_option";
var span = append(div, 'span');
for(var i in value)
{
var d = append(span, 'div');
d.innerHTML = value[i];
}
}
return div;
}
function append_options(parent, name, selected, choices)
{
var select = append(parent, 'select');
select.style.minWidth = "5em";
select.name = name;
for(var i in choices)
{
var s = (typeof choices[i] != 'object');
var choice_text = " " + (s ? choices[i] : choices[i][0]);
var choice_value = "" + (s ? choices[i] : choices[i][1]);
var option = append(select, 'option');
option.value = choice_value;
option.selected = (choice_value == selected) ? "selected" : "";
option.innerHTML= choice_text;
}
return select;
}
function append_selection(parent, title, name, selected, choices)
{
var p = append(parent, 'div');
var label = append(p, 'label');
p.className = "select_option";
label.innerHTML = title + ":";
append_options(p, name, selected, choices);
return p;
}
//append an input field
//e.g. append_input(parent, "Name", "name_string", "MyName")
function append_input(parent, title, name, value)
{
var div = append(parent, 'div');
var label = create('label');
var input = create('input');
label.innerHTML = title + ":";
input.value = (typeof value == "undefined") ? "" : value;
input.name = name;
input.type = "text";
div.appendChild(label);
div.appendChild(input);
return div;
}
//append a radio field
//e.g. append_radio(parent, "Enabled", "enabled", 0, [["Yes", 1], ["No", 0])
function append_radio(parent, title, name, selected, choices) {
return _selection("radio", parent, title, name, [selected], choices);
}
//append a checkbox field
//e.g. append_check(parent, "Enabled", "enabled", ["grass"], [["Grass", "grass"], ["Butter", "butter"]])
function append_check(parent, title, name, selected, choices) {
return _selection("checkbox", parent, title, name, selected, choices);
}
function _selection(type, parent, title, name, selected, choices)
{
var p = append(parent, 'div');
var label = append(p, 'label');
var span = append(p, 'span');
p.className = "radio_option";
label.innerHTML = title + ":";
for (var i in choices)
{
var s = (typeof choices[i] == 'string');
var choice_text = "" + (s ? choices[i] : choices[i][0]);
var choice_value = "" + (s ? choices[i] : choices[i][1]);
var choice_help = s ? undefined : choices[i][2];
var div = append(span, 'div');
var input = append(div, 'input');
var label = append(div, 'label');
input.name = name;
input.value = choice_value;
input.data = choice_value; //for IE :-(
input.type = type;
if(inArray(choice_value, selected))
input.checked = "checked"
label.innerHTML = " " + choice_text;
if(choice_text == "_")
hide(div);
if(choice_help) {
addHelpText(label, choice_help);
}
}
return p;
}
//from jx_compressed.js
jx={getHTTPObject:function(){var A=false;if(typeof ActiveXObject!="undefined"){try{A=new ActiveXObject("Msxml2.XMLHTTP")}catch(C){try{A=new ActiveXObject("Microsoft.XMLHTTP")}catch(B){A=false}}}else{if(window.XMLHttpRequest){try{A=new XMLHttpRequest()}catch(C){A=false}}}return A},load:function(url,callback,format){var http=this.init();if(!http||!url){return }if(http.overrideMimeType){http.overrideMimeType("text/xml")}if(!format){var format="text"}format=format.toLowerCase();var now="uid="+new Date().getTime();url+=(url.indexOf("?")+1)?"&":"?";url+=now;http.open("GET",url,true);http.onreadystatechange=function(){if(http.readyState==4){if(http.status==200){var result="";if(http.responseText){result=http.responseText}if(format.charAt(0)=="j"){result=result.replace(/[\n\r]/g,"");result=eval("("+result+")")}if(callback){callback(result)}}else{if(error){error(http.status)}}}};http.send(null)},init:function(){return this.getHTTPObject()}}

View File

@ -0,0 +1,226 @@
/* common */
* { margin:0; padding:0; }
a { text-decoration: none; }
li { list-style-type: none; }
html {
font: 90%/1.3 arial,sans-serif;
padding:1em;
background:#fafafa;
}
body {
font: normal 16px verdana,arial,'Bitstream Vera Sans',helvetica,sans-serif;
}
/* specific */
.mac {
color: #0033CC;
cursor: help;
}
#nds_files label {
width: 18em;
}
#nds_macs {
margin-bottom: 2em;
}
#wifiscan table {
text-align: center;
}
#wifiscan td:nth-of-type(1) {
text-align: left;
}
#help {
padding: 5px;
height: 0px;
position: absolute;
min-height: 50px;
background-color: #f2f2f2;
display:none;
border: 2px dotted grey;
}
#switches label {
width: 6em;
}
/* forms */
legend {
color: #0b77b7;
font-size: 1.2em;
}
label {
float: left;
width: 12em;
text-align: right;
margin-right: 1em;
white-space: nowrap;
}
fieldset {
border: 1px solid #ddd;
padding: 0.5em;
margin: 0.5em;
width: 36em;
}
fieldset fieldset {
width: auto;
}
fieldset > * {
margin: 0.3em 0;
clear: both;
}
fieldset div > * {
display: inline-block;
vertical-align: middle;
}
input {
padding: 0.15em;
width: 15em;
border: 1px solid #ddd;
background: #fafafa;
font: bold 0.95em arial, sans-serif;
-moz-border-radius: 0.4em;
-khtml-border-radius: 0.4em;
}
input:hover, input:focus {
border-color: #c5c5c5;
background: #f6f6f6;
}
select {
min-width: 4em;
}
option {
padding-right: 1em;
}
.radio_option div {
float: left;
white-space: nowrap;
clear: none;
}
.radio_option div label, .radio_option div input {
vertical-align: middle;
display: inline;
float: none;
width: auto;
background: none;
border: none;
}
.select_option label {
font-size: 1em;
color: #000;
}
.list_option div {
clear: left;
margin: 0;
padding: 0;
float: left;
list-style: none;
}
/* navigation */
#globalnav {
position: relative;
float: auto;
width: 98%;
padding: 0 0 1.75em 1em;
margin: 0;
margin-bottom: 2%;
list-style: none;
line-height: 1em;
}
#globalnav li {
float: left;
margin: 0;
padding: 0;
}
#globalnav a {
display: block;
color: #444;
text-decoration: none;
font-weight: bold;
background: #ddd;
margin: 0;
padding: 0.25em 1em;
border-left: 1px solid #fff;
border-top: 1px solid #fff;
border-right: 1px solid #aaa;
}
#globalnav a:hover,
#globalnav a:active,
#globalnav a.here:link,
#globalnav a.here:visited {
background: #bbb;
}
#globalnav a.here:link,
#globalnav a.here:visited {
position: relative;
z-index: 102;
}
/* sub-navigation */
#globalnav ul {
position: absolute;
left: 0;
top: 1.5em;
float: left;
background: #bbb;
width: 100%;
margin: 0;
padding: 0.25em 0.25em 0.25em 1em;
list-style: none;
border-top: 1px solid #fff;
}
#globalnav ul li {
float: left;
display: block;
margin-top: 1px;
}
#globalnav ul a {
background: #bbb;
color: #fff;
display: inline;
margin: 0;
padding: 0 1em;
border: 0;
}
#globalnav ul a:hover,
#globalnav ul a:active,
#globalnav ul a.here:link,
#globalnav ul a.here:visited {
color: #444;
}

View File

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<title>Upgrade</title>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="style.css" />
<script src="shared.js"></script>
<script src="upgrade.js"></script>
</head>
<body onload="init();">
<fieldset>
<legend>Router Zur&#252;cksetzen</legend>
<div>
<button type="button" onclick="restore_firmware()">Zur&#252;cksetzen</button>
</div>
<div><br />Alle Einstellungen werden zur&#252;ckgesetzt und der Router startet neu.</div>
</fieldset>
<fieldset>
<legend>Manuelles Update</legend>
<div id="selected_image"></div>
<form action="/cgi-bin/upgrade" enctype="multipart/form-data" method="post">
<div class="radio_option">
<label>
<input type="file" id="import_file" name="firmware" onchange="$('selected_image').innerHTML=this.value.replace(/^.*[\\\/](.*)$/, '$1');" style="visibility:hidden;position:absolute;top:-50;left:-50"/>
<input type="hidden" name="func" value="apply_firmware" />
<button type="button" onclick="$('import_file').click()">Image Ausw&auml;hlen</button>
<button type="submit">Senden</button>
</label>
<div>
<input type="checkbox" name="keep_config" value="yes" />
<label>Konfiguration erhalten</label>
</div>
</div>
</form>
<div><br />Hier kann ein Freifunk-Image verwendet werden (*-sysupgrade.bin) oder die Firmware des Routerherstellers.</div>
</fieldset>
</body>
</html>

View File

@ -0,0 +1,12 @@
function init() {
/* Nothing to do */
}
function restore_firmware() {
if(!confirm("Sollen alle Einstellungen zur\xFCckgesetzt werden?")) return;
send("/cgi-bin/upgrade", { func : 'restore_firmware' }, function(text) {
setText('msg', text);
});
}

View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<title>Wifiscan</title>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="style.css" />
<script src="shared.js"></script>
<script src="wifiscan.js"></script>
</head>
<body onload="init();">
<fieldset id="wifiscan">
<legend>Wifi Scan</legend>
<div>
<select id="wifiscan_selection"></select>
<button type="button" onclick="wifi_scan()">Scan starten</button>
</div>
<table id="wifiscan_table" style="display: none">
<tr><th>Name</th><th>Kanal</th><th>Signal</th><th>Typ</th></tr>
<tbody id="wifiscan_tbody"></tbody>
</table>
</fieldset>
</body>
</html>

View File

@ -0,0 +1,77 @@
function fetch(regex, data)
{
var result = data.match(regex);
return result ? result[1] : "";
}
function append_td(tr, value) {
append(tr, 'td').innerHTML = value ? value : "?";
}
function wifi_scan()
{
var s = $('wifiscan_selection');
var device = s.options[s.selectedIndex].value;
send("/cgi-bin/misc", {func:'wifiscan', device:device}, function(data) {
var tbody = $("wifiscan_tbody");
removeChilds(tbody);
var items = data.split(/BSS /).filter(Boolean);
for(var i = 0; i < items.length; ++i)
{
var item = items[i];
var ssid = fetch(/SSID: (.*)\n/, item);
var channel = fetch(/channel (.*)\n/, item);
var signal = fetch(/signal: (.*)\n/, item);
var capability = fetch(/capability: (.*)\n/, item);
var mesh_id = fetch(/MESH ID: (.*)\n/, item);
var tr = append(tbody, 'tr');
append_td(tr, mesh_id ? mesh_id : ssid);
append_td(tr, channel);
append_td(tr, signal);
//determine the wifi mode
if(mesh_id) {
append_td(tr, " 802.11s");
} else if(/IBSS/.test(capability)) {
append_td(tr, " AdHoc");
} else if(/ESS/.test(capability)) {
append_td(tr, " AccessPoint");
} else {
append_td(tr, " ???");
}
}
var table = $('wifiscan_table');
show(table);
});
}
function add_list_entry(device, ifname) {
var list = $('wifiscan_selection');
var o = append(list, 'option');
o.style.paddingRight = "1em";
o.innerHTML = device;
o.value = ifname;
}
/*
* Create a selection of wireless devices
* represented as the first interface found.
*/
function init() {
send("/cgi-bin/misc", {func:'wifi_status'}, function(data) {
var data = JSON.parse(data);
for(var device in data) {
var interfaces = data[device].interfaces;
if(interfaces.length == 0)
continue;
var ifname = interfaces[0].ifname ;
if(typeof(ifname) == 'string')
add_list_entry(device, ifname);
}
});
}

View File

@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=fff
PKG_VERSION:=0.0.1
PKG_RELEASE:=3
PKG_RELEASE:=4
PKG_BUILD_DIR:=$(BUILD_DIR)/fff
@ -14,7 +14,7 @@ define Package/fff-base
DEFAULT:=y
TITLE:= Freifunk-Franken Base
URL:=http://www.freifunk-franken.de
DEPENDS:=+micrond +fff-nodewatcher
DEPENDS:=+micrond +fff-nodewatcher +fff-web
endef
define Package/fff-base/description