diff --git a/.gitignore b/.gitignore
index 2ab3a11..93cd2d3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,6 @@
/env/
local-lighttpd/etc
local-lighttpd/port-*-etc
+/.vagrant
+/.cache
+/dist
diff --git a/Makefile b/Makefile
index aabaece..ffa7b89 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ NODEJS=$(if $(shell which nodejs),nodejs,node)
PIP_USER_SWITCH=$(if $(VIRTUAL_ENV),,--user)
TEMPLATES_JS=app/js/templates.js
-HANDLEBARS_FILES=app/templates/*.handlebars # Used to generate templates.js
+HANDLEBARS_FILES=$(wildcard app/templates/*.handlebars) # Used to generate templates.js
IMAGE=cerowrt/releases/openwireless-openwrt-squashfs-sysupgrade.bin
.PHONY: all
@@ -52,7 +52,7 @@ deps:
# This should depend on "all" instead. See note below for assert_templates_js_up_to_date
.PHONY: test
test: assert_templates_js_up_to_date deps
- /usr/bin/env python2.7 -m unittest discover -s test/ -p '*_test.py'
+ scripts/unit
$(NODEJS) -e "require('grunt').tasks(['test']);"
.PHONY: test-selenium
diff --git a/OWrt/config-OWrt b/OWrt/config-OWrt
index febcbee..c0db554 100644
--- a/OWrt/config-OWrt
+++ b/OWrt/config-OWrt
@@ -1103,11 +1103,11 @@ CONFIG_BUSYBOX_DEFAULT_FEATURE_NTPD_SERVER=y
CONFIG_BUSYBOX_DEFAULT_ROUTE=y
# CONFIG_BUSYBOX_DEFAULT_SLATTACH is not set
# CONFIG_BUSYBOX_DEFAULT_TCPSVD is not set
-CONFIG_BUSYBOX_DEFAULT_TELNET=y
-CONFIG_BUSYBOX_DEFAULT_FEATURE_TELNET_TTYPE=y
+# CONFIG_BUSYBOX_DEFAULT_TELNET is not set
+# CONFIG_BUSYBOX_DEFAULT_FEATURE_TELNET_TTYPE is not set
# CONFIG_BUSYBOX_DEFAULT_FEATURE_TELNET_AUTOLOGIN is not set
-CONFIG_BUSYBOX_DEFAULT_TELNETD=y
-CONFIG_BUSYBOX_DEFAULT_FEATURE_TELNETD_STANDALONE=y
+# CONFIG_BUSYBOX_DEFAULT_TELNETD is not set
+# CONFIG_BUSYBOX_DEFAULT_FEATURE_TELNETD_STANDALONE is not set
# CONFIG_BUSYBOX_DEFAULT_FEATURE_TELNETD_INETD_WAIT is not set
# CONFIG_BUSYBOX_DEFAULT_TFTP is not set
# CONFIG_BUSYBOX_DEFAULT_TFTPD is not set
@@ -1911,11 +1911,11 @@ CONFIG_BUSYBOX_CONFIG_FEATURE_NTPD_SERVER=y
CONFIG_BUSYBOX_CONFIG_ROUTE=y
# CONFIG_BUSYBOX_CONFIG_SLATTACH is not set
# CONFIG_BUSYBOX_CONFIG_TCPSVD is not set
-CONFIG_BUSYBOX_CONFIG_TELNET=y
-CONFIG_BUSYBOX_CONFIG_FEATURE_TELNET_TTYPE=y
+# CONFIG_BUSYBOX_CONFIG_TELNET is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_TELNET_TTYPE is not set
# CONFIG_BUSYBOX_CONFIG_FEATURE_TELNET_AUTOLOGIN is not set
-CONFIG_BUSYBOX_CONFIG_TELNETD=y
-CONFIG_BUSYBOX_CONFIG_FEATURE_TELNETD_STANDALONE=y
+# CONFIG_BUSYBOX_CONFIG_TELNETD is not set
+# CONFIG_BUSYBOX_CONFIG_FEATURE_TELNETD_STANDALONE is not set
# CONFIG_BUSYBOX_CONFIG_FEATURE_TELNETD_INETD_WAIT is not set
# CONFIG_BUSYBOX_CONFIG_TFTP is not set
# CONFIG_BUSYBOX_CONFIG_TFTPD is not set
@@ -2047,6 +2047,27 @@ CONFIG_BUSYBOX_CONFIG_SH_MATH_SUPPORT_64=y
# CONFIG_BUSYBOX_CONFIG_SYSLOGD is not set
# CONFIG_BUSYBOX_CONFIG_KLOGD is not set
CONFIG_BUSYBOX_CONFIG_LOGGER=y
+
+#
+#zoneinfo
+#
+
+CONFIG_PACKAGE_zoneinfo-africa=y
+CONFIG_PACKAGE_zoneinfo-asia=y
+CONFIG_PACKAGE_zoneinfo-atlantic=y
+CONFIG_PACKAGE_zoneinfo-australia-nz=y
+CONFIG_PACKAGE_zoneinfo-core=y
+CONFIG_PACKAGE_zoneinfo-europe=y
+CONFIG_PACKAGE_zoneinfo-india=y
+CONFIG_PACKAGE_zoneinfo-middleeast=y
+CONFIG_PACKAGE_zoneinfo-northamerica=y
+CONFIG_PACKAGE_zoneinfo-pacific=y
+CONFIG_PACKAGE_zoneinfo-poles=y
+CONFIG_PACKAGE_zoneinfo-simple=y
+CONFIG_PACKAGE_zoneinfo-southamerica=y
+
+
+
CONFIG_PACKAGE_ca-certificates=y
# CONFIG_PACKAGE_dnsmasq is not set
# CONFIG_PACKAGE_dnsmasq-dhcpv6 is not set
@@ -3157,7 +3178,7 @@ CONFIG_PACKAGE_in-jabberd=m
# CONFIG_PACKAGE_ncat-ssl is not set
# CONFIG_PACKAGE_ndiff is not set
# CONFIG_PACKAGE_nmap is not set
-CONFIG_PACKAGE_nmap-ssl=m
+# CONFIG_PACKAGE_nmap-ssl is not set
# CONFIG_PACKAGE_nping is not set
#
@@ -3523,7 +3544,7 @@ CONFIG_PACKAGE_authsae=m
CONFIG_PACKAGE_bing=m
# CONFIG_PACKAGE_bismark-ditg is not set
CONFIG_PACKAGE_bwping=m
-CONFIG_PACKAGE_ccnx=m
+# CONFIG_PACKAGE_ccnx is not set
CONFIG_PACKAGE_chat=y
CONFIG_PACKAGE_debloat=y
CONFIG_PACKAGE_ds-lite=y
@@ -3628,8 +3649,8 @@ CONFIG_PACKAGE_tor=y
# CONFIG_PACKAGE_tor-alpha is not set
# CONFIG_PACKAGE_tor-alpha-fw-helper is not set
# CONFIG_PACKAGE_tor-alpha-geoip is not set
-CONFIG_PACKAGE_tor-fw-helper=m
-CONFIG_PACKAGE_tor-geoip=m
+# CONFIG_PACKAGE_tor-fw-helper is not set
+# CONFIG_PACKAGE_tor-geoip is not set
# CONFIG_PACKAGE_uclient-fetch is not set
# CONFIG_PACKAGE_uqmi is not set
CONFIG_PACKAGE_vnstat=m
@@ -3741,7 +3762,7 @@ CONFIG_PACKAGE_bash=m
# CONFIG_PACKAGE_bismark-netexp is not set
# CONFIG_PACKAGE_bzip2 is not set
# CONFIG_PACKAGE_cal is not set
-CONFIG_PACKAGE_cerowrt-chrome=y
+# CONFIG_PACKAGE_cerowrt-chrome is not set
CONFIG_PACKAGE_cerowrt-interfaces=y
CONFIG_PACKAGE_cerowrt-scripts=y
CONFIG_PACKAGE_collectd=m
@@ -3807,7 +3828,7 @@ CONFIG_PACKAGE_dbus=y
CONFIG_PACKAGE_fconfig=m
# CONFIG_PACKAGE_flock is not set
# CONFIG_PACKAGE_getopt is not set
-CONFIG_PACKAGE_gnugol=m
+# CONFIG_PACKAGE_gnugol is not set
CONFIG_PACKAGE_gnupg=y
CONFIG_PACKAGE_haserl=m
# CONFIG_HASERL_with_lua is not set
@@ -3845,9 +3866,9 @@ CONFIG_PACKAGE_libjson-script=y
CONFIG_PACKAGE_mount-utils=y
# CONFIG_PACKAGE_mountd is not set
# CONFIG_PACKAGE_namei is not set
-CONFIG_PACKAGE_nut=m
-CONFIG_PACKAGE_nut-client=m
-CONFIG_PACKAGE_nut-driver-apcsmart=m
+# CONFIG_PACKAGE_nut is not set
+# CONFIG_PACKAGE_nut-client is not set
+# CONFIG_PACKAGE_nut-driver-apcsmart is not set
# CONFIG_PACKAGE_nut-driver-apcsmart-old is not set
# CONFIG_PACKAGE_nut-driver-bcmxcp is not set
# CONFIG_PACKAGE_nut-driver-bcmxcp_usb is not set
@@ -3859,10 +3880,10 @@ CONFIG_PACKAGE_nut-driver-apcsmart=m
# CONFIG_PACKAGE_nut-driver-richcomm_usb is not set
# CONFIG_PACKAGE_nut-driver-snmp-ups is not set
# CONFIG_PACKAGE_nut-driver-tripplite_usb is not set
-CONFIG_PACKAGE_nut-driver-usbhid-ups=m
-CONFIG_PACKAGE_nut-logger=m
-CONFIG_PACKAGE_nut-monitor=m
-CONFIG_PACKAGE_nut-server=m
+# CONFIG_PACKAGE_nut-driver-usbhid-ups is not set
+# CONFIG_PACKAGE_nut-logger is not set
+# CONFIG_PACKAGE_nut-monitor is not set
+# CONFIG_PACKAGE_nut-server is not set
# CONFIG_PACKAGE_nut-driver-bestfcom is not set
# CONFIG_PACKAGE_nut-driver-bestfortress is not set
# CONFIG_PACKAGE_nut-driver-bestuferrups is not set
@@ -3872,7 +3893,7 @@ CONFIG_PACKAGE_nut-server=m
# CONFIG_PACKAGE_nut-driver-etapro is not set
# CONFIG_PACKAGE_nut-driver-everups is not set
# CONFIG_PACKAGE_nut-driver-gamatronic is not set
-CONFIG_PACKAGE_nut-driver-genericups=m
+# CONFIG_PACKAGE_nut-driver-genericups is not set
# CONFIG_PACKAGE_nut-driver-isbmex is not set
# CONFIG_PACKAGE_nut-driver-liebert is not set
# CONFIG_PACKAGE_nut-driver-liebert-esp2 is not set
@@ -3885,7 +3906,7 @@ CONFIG_PACKAGE_nut-driver-genericups=m
# CONFIG_PACKAGE_nut-driver-oneac is not set
# CONFIG_PACKAGE_nut-driver-optiups is not set
# CONFIG_PACKAGE_nut-driver-powercom is not set
-CONFIG_PACKAGE_nut-driver-powerpanel=m
+# CONFIG_PACKAGE_nut-driver-powerpanel is not set
# CONFIG_PACKAGE_nut-driver-rhino is not set
# CONFIG_PACKAGE_nut-driver-safenet is not set
# CONFIG_PACKAGE_nut-driver-solis is not set
diff --git a/README.md b/README.md
index 2a07e9b..6faee05 100644
--- a/README.md
+++ b/README.md
@@ -8,51 +8,52 @@ OpenWireless router firmware, which is based off of Cerowrt and OpenWRT.
More details about the OpenWireless project can be found at
https://openwireless.org/.
-# Quick Look
-
-If you'd just like to take a quick look at the web UI, we have set up
-several instances of the web UI to be publicly accessible. Please try out one of
-these instances and report to us any vulnerabilities you find. Feel free to set
-an admin password: These instances will reset at the top of each hour.
-
-[0](http://ow.crud.net:8000)
-[1](http://ow.crud.net:8001)
-[2](http://ow.crud.net:8002)
-[3](http://ow.crud.net:8003)
-[4](http://ow.crud.net:8004)
-[5](http://ow.crud.net:8005)
-[6](http://ow.crud.net:8006)
-[7](http://ow.crud.net:8007)
-[8](http://ow.crud.net:8008)
-[9](http://ow.crud.net:8009)
-[10](http://ow.crud.net:8010)
-[11](http://ow.crud.net:8011)
-[12](http://ow.crud.net:8012)
-[13](http://ow.crud.net:8013)
-[14](http://ow.crud.net:8014)
-[15](http://ow.crud.net:8015)
-[16](http://ow.crud.net:8016)
-[17](http://ow.crud.net:8017)
-[18](http://ow.crud.net:8018)
-[19](http://ow.crud.net:8019)
-
# Getting Started
+## Ubuntu/Debian users:
+
Get the packages you need and install a git hook to run tests before push:
- ./install-dev-dependencies.sh
+```
+./install-dev-dependencies.sh
+```
+
+## Vagrant users:
+
+Requirements:
+
+* [vagrant 1.5+](https://www.vagrantup.com/)
+* [virtualbox 4.3.12+](https://www.virtualbox.org/)
+
+Getting started with vagrant is done with:
+
+```
+vagrant up
+```
+
+You can then connect with the virtual machine with:
+
+```
+vagrant ssh
+```
+
+**NOTE: the project root is mounted at ```/vagrant```**
+
+Further instructions assume you are connected to the VM in the /vagrant directory.
+## Boot frontend
Try out the web UI locally:
./local-lighttpd/run-local-lighttpd.sh
firefox http://localhost:8000/
+## Deploy changes to router
Sync the web UI to your router:
./sendAppToRouter --continuous
firefox http://gw.home.lan/
-# Running tests
+## Running tests
./run-tests.sh
diff --git a/Vagrantfile b/Vagrantfile
new file mode 100644
index 0000000..a5ac0e2
--- /dev/null
+++ b/Vagrantfile
@@ -0,0 +1,27 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
+VAGRANTFILE_API_VERSION = "2"
+
+Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
+ config.vm.box = "ubuntu/trusty64"
+
+ config.vm.provider "virtualbox" do |v|
+ v.memory = 4048
+ v.cpus = 4
+ end
+
+ config.vm.provision "shell", inline: <
+
diff --git a/app/css/admin-style.css b/app/css/admin-style.css
index c5d0524..c2d3032 100644
--- a/app/css/admin-style.css
+++ b/app/css/admin-style.css
@@ -1,5 +1,5 @@
@import url(oswald-font.css);
-header, .network, footer {
+header, .network, #check-for-updates div {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
@@ -312,7 +312,7 @@ h2 small {
display: none;
}
-footer {
+#check-for-updates div {
-ms-flex-preferred-size: 44px;
-webkit-flex-basis: 44px;
flex-basis: 44px;
@@ -336,13 +336,18 @@ footer img {
#enterSshKey {
display: none;
padding: 1em;
+ padding-bottom: 0;
+}
+#enterSshKey .controls {
+ margin: 0;
+ padding: 0;
+ text-align: right;
}
#input-SSH {
width: 100%;
height: 11em;
}
#cancel-SSH, #submit-SSH {
- float: right;
outline: medium none;
background: none repeat scroll 0% 0% #00ADEE;
border: 2px solid #00ADEE;
@@ -356,3 +361,19 @@ label {
padding-left: 1em;
padding-bottom: 1em;
}
+
+#check-for-updates .loading-message {
+ display: none;
+}
+
+#check-for-updates .message {
+ display: flex;
+}
+
+#check-for-updates.loading .loading-message {
+ display: flex;
+}
+
+#check-for-updates.loading .message {
+ display: none;
+}
diff --git a/app/css/style.css b/app/css/style.css
index 652b753..6788e99 100644
--- a/app/css/style.css
+++ b/app/css/style.css
@@ -147,4 +147,4 @@ p {
.changePassword {
display: none;
-}
+}
\ No newline at end of file
diff --git a/app/dashboard.html b/app/dashboard.html
index f10cfe0..28e39e7 100644
--- a/app/dashboard.html
+++ b/app/dashboard.html
@@ -43,8 +43,16 @@
Dashboard
WAN IP: Loading LAN IP: Loading
diff --git a/app/js/changePassword.js b/app/js/changePassword.js
index a46ff66..f0b8a2d 100644
--- a/app/js/changePassword.js
+++ b/app/js/changePassword.js
@@ -61,20 +61,7 @@ var changePassword = (function() {
*/
var setTimeZone = function(response) {
-
- /**
- * returns a POSIX compatible timezone string
- * since we can't get the real timezone we return
- * in the format off EFF\{offset\}local
- */
- var getTzString = function() {
- var d = new Date();
- var tzo = 1 + (d.getTimezoneOffset() / 60)
- var tzstr = "EFF" + tzo + "local\n"
- return tzstr;
- };
-
- var setTzRequest = { "jsonrpc": "2.0", "method": "set_timezone", "params": [getTzString()], "id": 1 };
+ var setTzRequest = { "jsonrpc": "2.0", "method": "set_timezone", "params": [jstz.determine().name()], "id": 1 };
var request = {
'data': setTzRequest,
'url': setTzUrl,
diff --git a/app/js/dashboard.js b/app/js/dashboard.js
index 84c6fa2..817f3e3 100644
--- a/app/js/dashboard.js
+++ b/app/js/dashboard.js
@@ -47,7 +47,12 @@ var dashboardModule = (function(){
var displayDate = function(lastCheckDate){
var m_names = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
- var d = new Date(parseFloat(lastCheckDate));
+ var d = lastCheckDate;
+
+ if(!(d instanceof Date)) {
+ d = new Date(parseFloat(lastCheckDate));
+ }
+
var curr_date = d.getDate();
var curr_month = d.getMonth();
var curr_year = d.getFullYear();
@@ -136,7 +141,8 @@ var dashboardModule = (function(){
};
return {
- init: init
+ init: init,
+ displayDate: displayDate
};
})();
diff --git a/app/js/diceware.js b/app/js/diceware.js
index cd3be2d..2cea62a 100644
--- a/app/js/diceware.js
+++ b/app/js/diceware.js
@@ -25,7 +25,7 @@ Diceware.prototype.load = function(callback) {
if (line === '-----BEGIN PGP SIGNATURE-----') {
break;
}
- var myregexp = /^\d+\s*([^\s]+)$/;
+ var myregexp = /^\s*\d+\s*([^\s]+)\s*$/;
var match = myregexp.exec(line);
if (match != null) {
// matched text: match[0]
diff --git a/app/js/templates.js b/app/js/templates.js
index 7a35900..553f29b 100644
--- a/app/js/templates.js
+++ b/app/js/templates.js
@@ -201,7 +201,7 @@ function program1(depth0,data) {
if (helper = helpers.contents) { stack1 = helper.call(depth0, {hash:{},data:data}); }
else { helper = (depth0 && depth0.contents); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
buffer += escapeExpression(stack1)
- + " \n Submit \n Cancel \n
\n ";
+ + " \n \n Submit \n Cancel \n
\n \n ";
return buffer;
}
function program2(depth0,data) {
diff --git a/app/js/update.js b/app/js/update.js
index d59974a..01e191b 100644
--- a/app/js/update.js
+++ b/app/js/update.js
@@ -2,22 +2,39 @@ var updateModule = (function(){
var checkUpdateCallback = function(response){
if(response.result.status == "up-to-date"){
+ dashboardModule.displayDate(new Date());
alert("Your software is up-to-date!");
} else {
if(confirm("A new version is available. Would you like to update now?")){
requestModule.submitRequest(updateRequest);
}
}
+ $("#check-for-updates").removeClass("loading");
+ };
+
+ var errorCallback = function(response){
+ alert("Unable to update - check your internet connection");
+ };
+
+ var updateCallback = function(response){
+ if(response.result.status == "update-success"){
+ dashboardModule.displayDate(new Date());
+ alert("Successfully updated your software!");
+ } else {
+ alert("Unable to complete update.");
+ }
};
var checkUpdateRequest = {
"url": "/cgi-bin/routerapi/check_updates",
"successCallback": checkUpdateCallback,
+ "errorCallback": errorCallback,
"data": {}
};
var updateRequest = {
"url": "/cgi-bin/routerapi/update",
+ "successCallback": updateCallback,
"data": {}
};
@@ -34,6 +51,7 @@ var updateModule = (function(){
$(function() {
$('#checkForUpdate').click(function(){
+ $("#check-for-updates").addClass("loading");
updateModule.submitUpdateRequest();
});
});
diff --git a/app/lib/jstz-1.0.4.min.js b/app/lib/jstz-1.0.4.min.js
new file mode 100644
index 0000000..96e3dd8
--- /dev/null
+++ b/app/lib/jstz-1.0.4.min.js
@@ -0,0 +1,2 @@
+/*! jstz - v1.0.4 - 2012-12-12 */
+(function(e){var t=function(){"use strict";var e="s",n=function(e){var t=-e.getTimezoneOffset();return t!==null?t:0},r=function(e,t,n){var r=new Date;return e!==undefined&&r.setFullYear(e),r.setDate(n),r.setMonth(t),r},i=function(e){return n(r(e,0,2))},s=function(e){return n(r(e,5,2))},o=function(e){var t=e.getMonth()>7?s(e.getFullYear()):i(e.getFullYear()),r=n(e);return t-r!==0},u=function(){var t=i(),n=s(),r=i()-s();return r<0?t+",1":r>0?n+",1,"+e:t+",0"},a=function(){var e=u();return new t.TimeZone(t.olson.timezones[e])};return{determine:a,date_is_dst:o}}();t.TimeZone=function(e){"use strict";var n=null,r=function(){return n},i=function(){var e=t.olson.ambiguity_list[n],r=e.length,i=0,s=e[0];for(;i{{contents}}
- Submit
- Cancel
+
+ Submit
+ Cancel
+
{{/sshKey}}
diff --git a/etc/lighttpd/conf.d/10-alias.conf b/etc/lighttpd/conf.d/10-alias.conf
deleted file mode 100644
index def97c3..0000000
--- a/etc/lighttpd/conf.d/10-alias.conf
+++ /dev/null
@@ -1 +0,0 @@
-server.modules += ( "mod_alias" )
diff --git a/etc/lighttpd/conf.d/10-cgi.conf b/etc/lighttpd/conf.d/10-cgi.conf
deleted file mode 100644
index ed27799..0000000
--- a/etc/lighttpd/conf.d/10-cgi.conf
+++ /dev/null
@@ -1,33 +0,0 @@
-#######################################################################
-##
-## CGI modules
-## ---------------
-##
-## http://www.lighttpd.net/documentation/cgi.html
-##
-server.modules += ( "mod_cgi" )
-
-##
-## Plain old CGI handling
-##
-## For PHP don't forget to set cgi.fix_pathinfo = 1 in the php.ini.
-##
-cgi.assign = ( ".pl" => "/usr/bin/perl",
- ".cgi" => "/usr/bin/perl",
- ".rb" => "/usr/bin/ruby",
- ".erb" => "/usr/bin/eruby",
- ".py" => "/usr/bin/python" )
-
-##
-## to get the old cgi-bin behavior of apache
-##
-## Note: make sure that mod_alias is loaded if you uncomment the
-## next line. (see modules.conf)
-##
-#alias.url += ( "/cgi-bin" => server_root + "/cgi-bin" )
-#$HTTP["url"] =~ "^/cgi-bin" {
-# cgi.assign = ( "" => "" )
-#}
-
-##
-#######################################################################
diff --git a/etc/lighttpd/conf.d/10-expire.conf b/etc/lighttpd/conf.d/10-expire.conf
deleted file mode 100644
index 0ca0ab2..0000000
--- a/etc/lighttpd/conf.d/10-expire.conf
+++ /dev/null
@@ -1,22 +0,0 @@
-#######################################################################
-##
-## Expire Module
-## ---------------
-##
-## See http://www.lighttpd.net/documentation/expire.html
-##
-server.modules += ( "mod_expire" )
-
-##
-## assignes a expiration to all files below the specified path. The
-## specification of the time is made up of:
-##
-##
-##
-#expire.url = (
-# "/buggy/" => "access 2 hours",
-# "/images/" => "access plus 1 seconds 2 minutes"
-#)
-
-##
-#######################################################################
diff --git a/etc/lighttpd/conf.d/10-fastcgi.conf b/etc/lighttpd/conf.d/10-fastcgi.conf
deleted file mode 100644
index 49cff62..0000000
--- a/etc/lighttpd/conf.d/10-fastcgi.conf
+++ /dev/null
@@ -1,135 +0,0 @@
-#######################################################################
-##
-## FastCGI Module
-## ---------------
-##
-## http://www.lighttpd.net/documentation/fastcgi.html
-##
-server.modules += ( "mod_fastcgi" )
-
-##
-## PHP Example
-## For PHP don't forget to set cgi.fix_pathinfo = 1 in the php.ini.
-##
-## The number of php processes you will get can be easily calculated:
-##
-## num-procs = max-procs * ( 1 + PHP_FCGI_CHILDREN )
-##
-## for the php-num-procs example it means you will get 17*5 = 85 php
-## processes. you always should need this high number for your very
-## busy sites. And if you have a lot of RAM. :)
-##
-#fastcgi.server = ( ".php" =>
-# ( "php-local" =>
-# (
-# "socket" => socket_dir + "/php-fastcgi-1.socket",
-# "bin-path" => server_root + "/cgi-bin/php5",
-# "max-procs" => 1,
-# "broken-scriptfilename" => "enable",
-# )
-# ),
-# ( "php-tcp" =>
-# (
-# "host" => "127.0.0.1",
-# "port" => 9999,
-# "check-local" => "disable",
-# "broken-scriptfilename" => "enable",
-# )
-# ),
-#
-# ( "php-num-procs" =>
-# (
-# "socket" => socket_dir + "/php-fastcgi-2.socket",
-# "bin-path" => server_root + "/cgi-bin/php5",
-# "bin-environment" => (
-# "PHP_FCGI_CHILDREN" => "16",
-# "PHP_FCGI_MAX_REQUESTS" => "10000",
-# ),
-# "max-procs" => 5,
-# "broken-scriptfilename" => "enable",
-# )
-# ),
-# )
-
-##
-## Ruby on Rails Example
-##
-## Normally you only run one Rails application on one vhost.
-##
-#$HTTP["host"] == "rails1.example.com" {
-# server.document-root = server_root + "/rails/someapp/public"
-# server.error-handler-404 = "/dispatch.fcgi"
-# fastcgi.server = ( ".fcgi" =>
-# ("someapp" =>
-# ( "socket" => socket_dir + "/someapp-fcgi.socket",
-# "bin-path" => server_root + "/rails/someapp/public/dispatch.fcgi",
-# "bin-environment" => (
-# "RAILS_ENV" => "production",
-# "TMP" => home_dir + "/rails/someapp",
-# ),
-# )
-# )
-# )
-#}
-
-##
-## Another example with multiple rails applications on one vhost.
-##
-## http://blog.lighttpd.net/articles/2005/11/23/lighttpd-1-4-8-and-multiple-rails-apps
-##
-#$HTTP["host"] == "rails2.example.com" {
-# $HTTP["url"] =~ "^/someapp1" {
-# server.document-root = server_root + "/rails/someapp1/public"
-# server.error-handler-404 = "/dispatch.fcgi"
-# fastcgi.server = ( ".fcgi" =>
-# ("someapp1" =>
-# ( "socket" => socket_dir + "/someapp1-fcgi.socket",
-# "bin-path" => server_root + "/rails/someapp1/public/dispatch.fcgi",
-# "bin-environment" => (
-# "RAILS_ENV" => "production",
-# "TMP" => home_dir + "/rails/someapp1",
-# ),
-# "strip-request-uri" => "/someapp1/"
-# )
-# )
-# )
-# }
-#
-# $HTTP["url"] =~ "^/someapp2" {
-# server.document-root = server_root + "/rails/someapp2/public"
-# server.error-handler-404 = "/dispatch.fcgi"
-# fastcgi.server = ( ".fcgi" =>
-# ("someapp2" =>
-# ( "socket" => socket_dir + "/someapp2-fcgi.socket",
-# "bin-path" => server_root + "/rails/someapp2/public/dispatch.fcgi",
-# "bin-environment" => (
-# "RAILS_ENV" => "production",
-# "TMP" => home_dir + "/rails/someapp2",
-# ),
-# "strip-request-uri" => "/someapp2/"
-# )
-# )
-# )
-# }
-#}
-
-## chrooted webserver + external PHP
-##
-## $ spawn-fcgi -f /usr/bin/php-cgi -p 2000 -a 127.0.0.1 -C 8
-##
-## webserver chrooted to /srv/www/
-## php running outside the chroot
-#
-#fastcgi.server = (
-# ".php" => ((
-# "host" => "127.0.0.1",
-# "port" => "2000",
-# "docroot" => "/srv/www/servers/www.example.org/htdocs/"
-# )))
-#
-#server.chroot = "/srv/www"
-#server.document-root = "/servers/wwww.example.org/htdocs/"
-#
-
-##
-#######################################################################
diff --git a/etc/lighttpd/conf.d/10-redirect.conf b/etc/lighttpd/conf.d/10-redirect.conf
deleted file mode 100644
index c022c09..0000000
--- a/etc/lighttpd/conf.d/10-redirect.conf
+++ /dev/null
@@ -1 +0,0 @@
-server.modules += ( "mod_redirect" )
diff --git a/etc/lighttpd/conf.d/10-simple_vhost.conf b/etc/lighttpd/conf.d/10-simple_vhost.conf
deleted file mode 100644
index 220331e..0000000
--- a/etc/lighttpd/conf.d/10-simple_vhost.conf
+++ /dev/null
@@ -1,28 +0,0 @@
-#######################################################################
-##
-## Simple Virtual hosting
-## ------------------------
-##
-## http://www.lighttpd.net/documentation/simple-vhost.html
-##
-server.modules += ( "mod_simple_vhost" )
-
-## If you want name-based virtual hosting add the next three settings and load
-## mod_simple_vhost
-##
-## document-root =
-## virtual-server-root + virtual-server-default-host + virtual-server-docroot
-## or
-## virtual-server-root + http-host + virtual-server-docroot
-##
-simple-vhost.server-root = vhosts_dir + "/"
-simple-vhost.default-host = "default.example.com"
-simple-vhost.document-root = "/htdocs/"
-
-##
-## Print some errors for finding the document-root
-##
-#simple-vhost.debug = "enable"
-
-##
-#######################################################################
diff --git a/etc/openwrt_release b/etc/openwrt_release
index 925bd93..a43eee7 100644
--- a/etc/openwrt_release
+++ b/etc/openwrt_release
@@ -4,5 +4,5 @@ DISTRIB_TAINTS="no-all busybox"
DISTRIB_CODENAME="MVP-HOPE"
DISTRIB_TARGET="ar71xx/generic"
DISTRIB_REVISION="r41336"
-DISTRIB_RELEASE_DATE="1405377121"
+DISTRIB_RELEASE_DATE="1417020711"
DISTRIB_DESCRIPTION="OWrt MVP-HOPE r41336 3.10.44-6"
diff --git a/infra/etc/init/xvfb.conf b/infra/etc/init/xvfb.conf
new file mode 100644
index 0000000..21a3805
--- /dev/null
+++ b/infra/etc/init/xvfb.conf
@@ -0,0 +1,12 @@
+# Xvfb - Xvfb virtual X windows
+
+description "Xvfb server"
+
+start on runlevel [2345]
+stop on runlevel [!2345]
+
+respawn
+respawn limit 10 5
+umask 022
+
+exec /usr/bin/Xvfb :0 -screen 0 1024x768x24
diff --git a/infra/repositories.conf b/infra/repositories.conf
new file mode 100644
index 0000000..98d7d09
--- /dev/null
+++ b/infra/repositories.conf
@@ -0,0 +1,11 @@
+src/gz bufferbloat http://snapon.lab.bufferbloat.net/~cero2/cerowrt/wndr/3.10.50-1/packages
+src/gz barrier_breaker_base http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/base
+src/gz barrier_breaker_luci http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/luci
+src/gz barrier_breaker_management http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/management
+src/gz barrier_breaker_oldpackages http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/oldpackages
+src/gz barrier_breaker_packages http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/packages
+src/gz barrier_breaker_routing http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/routing
+src/gz barrier_breaker_telephony http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/telephony
+
+## This is the local package repository, do not remove!
+src imagebuilder file:packages
diff --git a/install-dev-dependencies.sh b/install-dev-dependencies.sh
index ff2394d..5c79f8a 100755
--- a/install-dev-dependencies.sh
+++ b/install-dev-dependencies.sh
@@ -1,11 +1,59 @@
#!/bin/bash -ex
# On Ubuntu and similar systems, install packages that are necessary and/or
# useful to build and debug OpenWireless.
-sudo apt-get install inotify-tools lighttpd nodejs npm python2.7 python-pip
+
+set -o nounset
+
+INSTALL_XVFB=""
+ACCEPT_INSTALL_PROMPTS=""
+
+while getopts "xa" ARG; do
+ case $ARG in
+ x)
+ INSTALL_XVFB=true
+ ;;
+ a)
+ ACCEPT_INSTALL_PROMPTS=--assume-yes
+ ;;
+ \?)
+ cat < "/www/cgi-bin" )
+alias.url += ( "/cgi-bin" => "%(CGI_ROOT)s" )
$HTTP["url"] =~ "^/cgi-bin" {
cgi.assign = ( "" => "" )
}
-$HTTP["host"] == "172.30.42.1" {
- url.redirect = (
- "^/(.*)" => "http://gw.home.lan/"
- )
-}
-
#### SSL engine
### use PFS
-# https://raymii.org/s/tutorials/Pass_the_SSL_Labs_Test_on_Lighttpd_%28Mitigate_the_CRIME_and_BEAST_attack_-_Disable_SSLv2_-_Enable_PFS%29.html
+# https://raymii.org/s/tutorials/Pass_the_SSL_Labs_Test_on_Lighttpd_%%28Mitigate_the_CRIME_and_BEAST_attack_-_Disable_SSLv2_-_Enable_PFS%%29.html
ssl.honor-cipher-order = "enable"
ssl.cipher-list = "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-RC4-SHA:ECDHE-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA"
ssl.use-sslv2 = "disable"
@@ -44,25 +38,24 @@ setenv.add-response-header = (
"X-Content-Type-Options" => "nosniff"
)
-server.port = 80
-server.bind = "172.30.42.1"
+server.port = %(HTTP_PORT)s
+server.bind = "%(BIND)s"
# When accessing on port 80, show the welcome page and warn the user that they
# are about to get a cert warning.
-$SERVER["socket"] == "172.30.42.1:80" {
+$SERVER["socket"] == "%(BIND)s:%(HTTP_PORT)s" {
index-file.names = ( "welcome.html" )
- # However, if they are logged in, take them straight to the HTTPS side of
- # things.
+
$HTTP["cookie"] =~ "logged_in" {
url.redirect = (
- "^/(.*)" => "https://gw.home.lan/"
+ "^/(.*)" => "https://%(APPLICATION_URL)s$0"
)
}
}
-$SERVER["socket"] == "172.30.42.1:443" {
+$SERVER["socket"] == "%(BIND)s:%(HTTPS_PORT)s" {
ssl.engine = "enable"
- ssl.pemfile = "/etc/lighttpd/lighttpd.pem"
+ ssl.pemfile = "%(PEM_FILE)s"
}
## mimetype mapping
@@ -87,7 +80,7 @@ mimetype.assign = (
)
## to help the rc.scripts
-server.pid-file = "/var/run/lighttpd.pid"
+server.pid-file = "%(PID_FILE)s"
## virtual directory listings
server.dir-listing = "enable"
@@ -95,7 +88,9 @@ server.dir-listing = "enable"
## change uid to (default: don't care)
# We'd like to run the server as root, but a couple of commands
# (ping and iptaccount) won't run as user www-data.
-server.username = "www-data"
-server.groupname = "www-data"
+server.username = "%(USER)s"
+server.groupname = "%(GROUP)s"
server.upload-dirs = ( "/tmp" )
+
+include_shell "cat conf.d/*.conf 2> /dev/null"
diff --git a/lighttpd/router.properties b/lighttpd/router.properties
new file mode 100644
index 0000000..d9c7de3
--- /dev/null
+++ b/lighttpd/router.properties
@@ -0,0 +1,10 @@
+DOC_ROOT=/www
+CGI_ROOT=/www/cgi-bin
+HTTP_PORT=80
+HTTPS_PORT=443
+BIND=172.30.42.1
+PID_FILE=/var/run/lighttpd.pid
+USER=www-data
+GROUP=www-data
+PEM_FILE=/etc/lighttpd/lighttpd.pem
+APPLICATION_URL=gw.home.lan
diff --git a/local-lighttpd/local-lighttpd.conf b/local-lighttpd/local-lighttpd.conf
deleted file mode 100644
index 226afe3..0000000
--- a/local-lighttpd/local-lighttpd.conf
+++ /dev/null
@@ -1,88 +0,0 @@
-# lighttpd configuration file for OpenWireless
-#
-## modules to load
-# all other module should only be loaded if really neccesary
-# - saves some time
-# - saves memory
-server.modules = (
- "mod_alias",
- "mod_setenv",
- "mod_simple_vhost",
- "mod_cgi",
- "mod_expire",
-)
-
-# force use of the "write" backend (closes: #2401)
-server.network-backend = "write"
-server.document-root = "REPO_DIR/app"
-server.follow-symlink = "disable"
-
-index-file.names = ( "index.html" )
-alias.url += ( "/cgi-bin/routerapi" => "REPO_DIR/routerapi" )
-$HTTP["url"] =~ "^/cgi-bin/routerapi" {
- cgi.assign = ( "" => "" )
-}
-
-#### SSL engine
-### use PFS
-# https://raymii.org/s/tutorials/Pass_the_SSL_Labs_Test_on_Lighttpd_%28Mitigate_the_CRIME_and_BEAST_attack_-_Disable_SSLv2_-_Enable_PFS%29.html
-ssl.honor-cipher-order = "enable"
-ssl.cipher-list = "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-RC4-SHA:ECDHE-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA"
-ssl.use-sslv2 = "disable"
-
-setenv.add-response-header = (
- "Content-Security-Policy" => "default-src 'self'; img-src 'self' data:",
- "X-Frame-Options" => "SAMEORIGIN",
- "X-Content-Type-Options" => "nosniff"
-)
-
-server.port = HTTP_PORT
-
-$SERVER["socket"] == ":HTTP_PORT" {
- index-file.names = ( "welcome.html" )
-}
-
-$SERVER["socket"] == ":HTTPS_PORT" {
- ssl.engine = "enable"
- ssl.pemfile = "./local-lighttpd.pem"
-}
-
-## mimetype mapping
-mimetype.assign = (
- ".pdf" => "application/pdf",
- ".class" => "application/octet-stream",
- ".pac" => "application/x-ns-proxy-autoconfig",
- ".swf" => "application/x-shockwave-flash",
- ".wav" => "audio/x-wav",
- ".gif" => "image/gif",
- ".jpg" => "image/jpeg",
- ".jpeg" => "image/jpeg",
- ".png" => "image/png",
- ".css" => "text/css",
- ".html" => "text/html; charset=utf-8",
- ".htm" => "text/html",
- ".js" => "text/javascript",
- ".txt" => "text/plain",
- ".dtd" => "text/xml",
- ".xml" => "text/xml",
- ".svg" => "image/svg+xml"
- )
-
-## to help the rc.scripts
-server.pid-file = "./local-lighttpd.pid"
-
-## virtual directory listings
-server.dir-listing = "enable"
-
-## change uid to (default: don't care)
-# We'd like to run the server as root, but a couple of commands
-# (ping and iptaccount) won't run as user www-data.
-#server.username = "www-data"
-#server.groupname = "www-data"
-
-server.upload-dirs = ( "/tmp" )
-
-setenv.add-environment = (
- "OVERRIDE_ETC" => var.CWD,
- "OVERRIDE_PATH" => var.CWD + "/.."
-)
diff --git a/local-lighttpd/run-local-lighttpd.sh b/local-lighttpd/run-local-lighttpd.sh
index 72ba1a5..e64db33 100755
--- a/local-lighttpd/run-local-lighttpd.sh
+++ b/local-lighttpd/run-local-lighttpd.sh
@@ -1,12 +1,18 @@
#!/bin/bash -ex
-DIR=$(dirname $0)
+DIR=$(cd `dirname $0` && pwd)
cd $DIR
HTTP_PORT=${HTTP_PORT:-8000}
HTTPS_PORT=$(($HTTP_PORT + 1000))
-ETC=port-$HTTP_PORT-etc
+ROOT=`mktemp -d /tmp/openwireless-frontend-XXXX`
+ETC=$ROOT/port-$HTTP_PORT-etc
+REPO_DIR=`cd $DIR/.. && pwd`
+DOC_ROOT=$REPO_DIR/app
+CGI_ROOT=$REPO_DIR
+LIGHTTPD_CONF_TEMPLATE=$REPO_DIR/lighttpd/lighttpd.conf.template
rm -rf $ETC
mkdir -m 0700 -p $ETC/auth
mkdir -m 0700 -p $ETC/dropbear
+cp -R *.py $ROOT
echo '{
"sqm.ge00.download": "0",
"sqm.ge00.upload": "0",
@@ -18,9 +24,28 @@ echo '{
"openwireless.use_at_last_ui_reset": "0",
"openwireless.setup_state": "set-password"
}' > $ETC/uci.json
-cp local-lighttpd.pem $ETC/
+cp local-lighttpd.pem $ETC/lighttpd.pem
-sed "s,REPO_DIR,$(readlink -f ..),; s,HTTP_PORT,$HTTP_PORT,; s,HTTPS_PORT,$HTTPS_PORT,;" local-lighttpd.conf > $ETC/local-lighttpd.conf
+$REPO_DIR/scripts/template $LIGHTTPD_CONF_TEMPLATE > $ETC/lighttpd.conf < $ETC/conf.d/local-test-server.conf < var.CWD,
+ "OVERRIDE_PATH" => var.CWD + "/.."
+)
+EOS
cd $ETC
echo "Access the web UI on http://localhost:$HTTP_PORT/"
-exec lighttpd -D -f local-lighttpd.conf "$@"
+exec lighttpd -D -f $ETC/lighttpd.conf "$@"
diff --git a/requirements.txt b/requirements.txt
index 876eda0..a86027e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,2 @@
mock==1.0.1
-selenium==2.42.1
+selenium==2.44.0
diff --git a/routerapi/accumulate_bytes b/routerapi/accumulate_bytes
index 01a3686..315dcb9 100644
--- a/routerapi/accumulate_bytes
+++ b/routerapi/accumulate_bytes
@@ -8,18 +8,19 @@ from subprocess import check_output
from get_bytecounts import get_device_and_byte_counts
-def disable_overutilized_network():
+def update_network_availability():
use_before_last_reset = float(uci.get("openwireless.use_before_last_reset"))
use_since_last_reset = float(uci.get("openwireless.use_since_last_reset"))
use_at_last_ui_reset = float(uci.get("openwireless.use_at_last_ui_reset"))
current_use = use_before_last_reset + use_since_last_reset - use_at_last_ui_reset
max_use = float(uci.get("openwireless.maxmonthlybandwidth"))*1000000
- if current_use > max_use:
- uci.set("wireless.@wifi-iface[1].disabled", "1")
+ current_state = uci.get("wireless.@wifi-iface[1].disabled")
+ new_state = "1" if current_use > max_use else "0"
+ if current_state != new_state:
+ uci.set("wireless.@wifi-iface[1].disabled", new_state)
uci.commit("wireless")
common.reset_wifi()
-
def update_openwireless_usage():
#times are in seconds
@@ -62,6 +63,10 @@ def update_openwireless_usage():
else:
increment_use_since_last_reset()
-update_openwireless_usage()
-disable_overutilized_network()
-uci.commit("openwireless")
+def main():
+ update_openwireless_usage()
+ update_network_availability()
+ uci.commit("openwireless")
+
+if __name__ == '__main__':
+ main()
diff --git a/routerapi/accumulate_bytes.py b/routerapi/accumulate_bytes.py
new file mode 120000
index 0000000..d0897fd
--- /dev/null
+++ b/routerapi/accumulate_bytes.py
@@ -0,0 +1 @@
+accumulate_bytes
\ No newline at end of file
diff --git a/routerapi/auth.py b/routerapi/auth.py
index 86269b6..a780323 100644
--- a/routerapi/auth.py
+++ b/routerapi/auth.py
@@ -80,6 +80,7 @@ class Auth:
RATE_LIMIT_DURATION = 86400 # One day in seconds
RATE_LIMIT_COUNT = 10
LOGGED_IN_COOKIE_NAME = 'logged_in'
+ PASSWORD_LENGTH_MIN = 8
def __init__(self, path = default_path()):
self.path = path
@@ -167,11 +168,16 @@ def is_password(self, candidate):
def save_password(self, new_password):
"""
Store a new password.
+ Returns True is the password was stored and False if the password
+ didn't fulfil all criteria.
"""
+ if len(new_password) < self.PASSWORD_LENGTH_MIN:
+ return False
# 55 iterations takes about 100 ms on a Netgear WNDR3800 or about 8ms on a
# Core2 Duo at 1200 MHz.
hashed = pbkdf2.crypt(new_password, iterations=55)
self.write(self.password_filename, hashed)
+ return True
def get_csrf_token(self):
"""
diff --git a/routerapi/change_password b/routerapi/change_password
index d4bf32b..a620445 100755
--- a/routerapi/change_password
+++ b/routerapi/change_password
@@ -29,7 +29,8 @@ def jsonrpc_change_password():
a = auth.Auth()
if a.is_password(old_password):
- a.save_password(new_password)
+ if not a.save_password(new_password):
+ common.render_error("Invalid password supplied.")
print "Content-Type: application/json"
print a.login_headers()
print
diff --git a/routerapi/change_password_first_time b/routerapi/change_password_first_time
index 30f928a..06dfa11 100755
--- a/routerapi/change_password_first_time
+++ b/routerapi/change_password_first_time
@@ -33,7 +33,8 @@ def jsonrpc_change_password_first_time(auth_path):
if a.password_exists():
common.render_error('Administrator password has already been set.')
else:
- a.save_password(new_password)
+ if not a.save_password(new_password):
+ common.render_error("Invalid password supplied.")
uci.set('openwireless.setup_state', 'setup-private-net')
uci.commit('openwireless')
print "Content-Type: application/json"
diff --git a/routerapi/check_updates b/routerapi/check_updates
index 44eba55..ab8bd56 100755
--- a/routerapi/check_updates
+++ b/routerapi/check_updates
@@ -14,6 +14,9 @@ try:
ret = "not-up-to-date"
else:
ret = "up-to-date"
+except OSError:
+ # catch call-errors and return error message
+ pass
finally:
nullfile.close()
diff --git a/routerapi/gen_tz_dictionary.py b/routerapi/gen_tz_dictionary.py
new file mode 100644
index 0000000..859c157
--- /dev/null
+++ b/routerapi/gen_tz_dictionary.py
@@ -0,0 +1,84 @@
+#!/usr/bin/python
+"""
+gen_tz_dictionary - Generate a python file containing a dictionary that maps
+Olson Time Zones to their POSIX equivalents.
+"""
+
+import os
+import sys
+import re
+
+TZ_DB = "/usr/share/zoneinfo"
+PY_TZ_FILE_PATH = "./tz_info.py"
+
+
+def generate_dictionary_file():
+ tz_info = get_zone_info()
+ if tz_info:
+ write_zone_file(get_zone_info())
+ exit(0)
+
+ # Exit with error status if we couldn't read zone info
+ exit(1)
+
+
+def get_zone_info(zone_dir=TZ_DB):
+ """
+ get_zone_info - parse zone info from zoneinfo database into
+ a python dictionary
+ """
+ tzd = {}
+ try:
+ with open(os.path.join(zone_dir, "zone.tab"), "r") as zonetab:
+ for line in zonetab:
+ # Skip comments and whitespace
+ if re.match("^#", line) or re.match("^\s+$", line):
+ continue
+
+ # Olson zone paths are the third column in the table
+ zone = re.split("\s+", line)[2]
+
+ try:
+ tzd[zone] = read_posix_zone(zone)
+ except EnvironmentError: # IOError or OSError
+ continue
+
+ return tzd
+
+ except EnvironmentError: # IOError or OSError
+ return False
+
+
+def read_posix_zone(zone):
+ """
+ read_posix_zone - return the posix time zone for a give olson time zone
+ @param string zone - olson time zone string
+ """
+ with open(os.path.join(TZ_DB, zone), "r") as zonefile:
+ # Return last line of file
+ return list(zonefile)[-1].rstrip()
+
+
+def write_zone_file(tz_dict):
+ """
+ write_zone_file - write a timezone dictionary to a new python file
+ @param dictionary tz_info - a dictionary mapping olson timezones to POSIX
+ equivalents
+ """
+ with open(PY_TZ_FILE_PATH, 'w') as py_file:
+ header = ("#!/usr/bin/python\n"
+ "\"\"\"\ntz_info - maps Olson time zones to POSIX equivalents\nAutogenerated by gen_tz_dictionary.py\n\"\"\"\n"
+ "tz_info = {\n")
+
+ footer = "}\n"
+
+ py_file.write(header)
+
+ for otz in tz_dict:
+ py_file.write(" \"{0}\": \"{1}\",\n".format(otz,tz_dict[otz]))
+
+ py_file.write(footer)
+
+
+if __name__ == '__main__':
+ generate_dictionary_file()
diff --git a/routerapi/set_private_ssid b/routerapi/set_private_ssid
index bbc29a1..a654e6b 100755
--- a/routerapi/set_private_ssid
+++ b/routerapi/set_private_ssid
@@ -16,7 +16,8 @@ def jsonrpc_set_private_ssid():
common.render_error(e.__str__())
except ValueError, e:
common.render_error(e.__str__())
-
+ if len(passphrase) < 8:
+ common.render_error("Passphrase must contain at least 8 characters.")
# TODO: filter input
uci.set('wireless.@wifi-iface[2].ssid', name)
uci.set('wireless.@wifi-iface[2].key', passphrase)
diff --git a/routerapi/set_timezone b/routerapi/set_timezone
index 33008b5..19a2a67 100755
--- a/routerapi/set_timezone
+++ b/routerapi/set_timezone
@@ -4,20 +4,21 @@ import os
import sys
import common
+from tz_info import tz_info
def jsonrpc_set_timezone(etc=common.get_etc()):
- """Accept a POSIX-style set timezone, with parameters like so:
+ """Accept an olson-style set timezone, with parameters like so:
{"jsonrpc":"2.0","method":"set_timezone","params":["timezonestring"],"id":1}
- Set the local timezone on the router by placing the POSIX compatible timezone string
+ Set the local timezone on the router by looking up and placing the POSIX compatible timezone string
in the /etc/TZ file.
"""
data = json.loads(sys.stdin.read())
try:
params = data["params"]
- tz_string = params[0]
+ tz_string = tz_info[params[0]]
except KeyError, e:
common.render_error(e.__str__())
except IndexError, e:
diff --git a/routerapi/tz_info.py b/routerapi/tz_info.py
new file mode 100644
index 0000000..bd9037f
--- /dev/null
+++ b/routerapi/tz_info.py
@@ -0,0 +1,423 @@
+#!/usr/bin/python
+"""
+tz_info - maps Olson time zones to POSIX equivalents
+Autogenerated by genTzDictionary.py
+"""
+tz_info = {
+ "Atlantic/Canary": "WET0WEST,M3.5.0/1,M10.5.0",
+ "Australia/Melbourne": "EST-10EST,M10.1.0,M4.1.0/3",
+ "Europe/Minsk": "FET-3",
+ "America/Nipigon": "EST5EDT,M3.2.0,M11.1.0",
+ "America/Miquelon": "PMST3PMDT,M3.2.0,M11.1.0",
+ "Pacific/Wallis": "WFT-12",
+ "Antarctica/Davis": "DAVT-7",
+ "Asia/Dhaka": "BDT-6",
+ "America/St_Lucia": "AST4",
+ "Asia/Kashgar": "CST-8",
+ "America/Phoenix": "MST7",
+ "Asia/Kuwait": "AST-3",
+ "Asia/Hong_Kong": "HKT-8",
+ "Arctic/Longyearbyen": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Europe/Guernsey": "GMT0BST,M3.5.0/1,M10.5.0",
+ "Europe/Paris": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Europe/Stockholm": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Pacific/Fiji": "FJT-12FJST,M10.3.1/146,M1.3.4/74",
+ "Pacific/Apia": "WST-13WSDT,M9.5.0/3,M4.1.0/4",
+ "Pacific/Pago_Pago": "SST11",
+ "Asia/Rangoon": "MMT-6:30",
+ "America/Mexico_City": "CST6CDT,M4.1.0,M10.5.0",
+ "America/Puerto_Rico": "AST4",
+ "Indian/Mauritius": "MUT-4",
+ "Europe/Berlin": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Europe/Zurich": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "America/Belem": "BRT3",
+ "Antarctica/Macquarie": "MIST-11",
+ "Asia/Krasnoyarsk": "KRAT-8",
+ "Atlantic/Bermuda": "AST4ADT,M3.2.0,M11.1.0",
+ "Australia/Currie": "EST-10EST,M10.1.0,M4.1.0/3",
+ "Asia/Tehran": "",
+ "Asia/Baku": "AZT-4AZST,M3.5.0/4,M10.5.0/5",
+ "America/St_Barthelemy": "AST4",
+ "America/Santarem": "BRT3",
+ "America/Danmarkshavn": "GMT0",
+ "America/Scoresbysund": "EGT1EGST,M3.5.0/0,M10.5.0/1",
+ "America/Eirunepe": "ACT5",
+ "America/Caracas": "VET4:30",
+ "Asia/Baghdad": "AST-3",
+ "Africa/Monrovia": "GMT0",
+ "America/St_Vincent": "AST4",
+ "America/Vancouver": "PST8PDT,M3.2.0,M11.1.0",
+ "Asia/Ho_Chi_Minh": "ICT-7",
+ "Europe/Busingen": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Asia/Thimphu": "BTT-6",
+ "Africa/Accra": "GMT0",
+ "America/Belize": "CST6",
+ "America/Edmonton": "MST7MDT,M3.2.0,M11.1.0",
+ "Asia/Tashkent": "UZT-5",
+ "Asia/Tokyo": "JST-9",
+ "Pacific/Kiritimati": "LINT-14",
+ "Australia/Sydney": "EST-10EST,M10.1.0,M4.1.0/3",
+ "Europe/Riga": "EET-2EEST,M3.5.0/3,M10.5.0/4",
+ "Asia/Dili": "TLT-9",
+ "Africa/Mbabane": "SAST-2",
+ "Asia/Oral": "ORAT-5",
+ "Asia/Aden": "AST-3",
+ "Europe/Isle_of_Man": "GMT0BST,M3.5.0/1,M10.5.0",
+ "Europe/Istanbul": "EET-2EEST,M3.5.0/3,M10.5.0/4",
+ "Asia/Magadan": "MAGT-12",
+ "Australia/Lindeman": "EST-10",
+ "Pacific/Galapagos": "GALT6",
+ "America/Bogota": "COT5",
+ "Africa/Asmara": "EAT-3",
+ "America/Chicago": "CST6CDT,M3.2.0,M11.1.0",
+ "Pacific/Kwajalein": "MHT-12",
+ "Australia/Broken_Hill": "CST-9:30CST,M10.1.0,M4.1.0/3",
+ "America/Cuiaba": "AMT4AMST,M10.3.0/0,M2.3.0/0",
+ "Indian/Christmas": "CXT-7",
+ "Asia/Jayapura": "WIT-9",
+ "Europe/Brussels": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Europe/Lisbon": "WET0WEST,M3.5.0/1,M10.5.0",
+ "Asia/Chongqing": "CST-8",
+ "America/Argentina/Cordoba": "ART3",
+ "America/Noronha": "FNT2",
+ "Europe/Podgorica": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Africa/Algiers": "CET-1",
+ "Africa/Harare": "CAT-2",
+ "Africa/Ndjamena": "WAT-1",
+ "America/Costa_Rica": "CST6",
+ "Europe/Ljubljana": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Indian/Mayotte": "EAT-3",
+ "Asia/Phnom_Penh": "ICT-7",
+ "America/Managua": "CST6",
+ "Asia/Brunei": "BNT-8",
+ "America/Tijuana": "PST8PDT,M3.2.0,M11.1.0",
+ "Pacific/Fakaofo": "TKT-13",
+ "America/Martinique": "AST4",
+ "America/Antigua": "AST4",
+ "America/Indiana/Indianapolis": "EST5EDT,M3.2.0,M11.1.0",
+ "America/Argentina/La_Rioja": "ART3",
+ "Pacific/Tahiti": "TAHT10",
+ "America/Pangnirtung": "EST5EDT,M3.2.0,M11.1.0",
+ "Europe/Zagreb": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "America/Asuncion": "PYT4PYST,M10.1.0/0,M3.4.0/0",
+ "Europe/Vienna": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Australia/Hobart": "EST-10EST,M10.1.0,M4.1.0/3",
+ "America/Juneau": "AKST9AKDT,M3.2.0,M11.1.0",
+ "America/Inuvik": "MST7MDT,M3.2.0,M11.1.0",
+ "America/Ojinaga": "MST7MDT,M3.2.0,M11.1.0",
+ "Asia/Seoul": "KST-9",
+ "Indian/Comoro": "EAT-3",
+ "Antarctica/Rothera": "ROTT3",
+ "Europe/Tallinn": "EET-2EEST,M3.5.0/3,M10.5.0/4",
+ "Indian/Mahe": "SCT-4",
+ "America/Argentina/Jujuy": "ART3",
+ "America/Creston": "MST7",
+ "America/Adak": "HAST10HADT,M3.2.0,M11.1.0",
+ "Asia/Singapore": "SGT-8",
+ "Africa/Nairobi": "EAT-3",
+ "America/Maceio": "BRT3",
+ "Asia/Urumqi": "CST-8",
+ "Europe/Moscow": "MSK-4",
+ "Asia/Pyongyang": "KST-9",
+ "Asia/Ulaanbaatar": "ULAT-8",
+ "America/Rainy_River": "CST6CDT,M3.2.0,M11.1.0",
+ "Indian/Maldives": "MVT-5",
+ "Asia/Colombo": "IST-5:30",
+ "Australia/Adelaide": "CST-9:30CST,M10.1.0,M4.1.0/3",
+ "America/Cambridge_Bay": "MST7MDT,M3.2.0,M11.1.0",
+ "Africa/Luanda": "WAT-1",
+ "Pacific/Chatham": "CHAST-12:45CHADT,M9.5.0/2:45,M4.1.0/3:45",
+ "America/Indiana/Winamac": "EST5EDT,M3.2.0,M11.1.0",
+ "Asia/Tbilisi": "GET-4",
+ "Europe/Gibraltar": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Asia/Karachi": "PKT-5",
+ "Asia/Harbin": "CST-8",
+ "Australia/Lord_Howe": "LHST-10:30LHST-11,M10.1.0,M4.1.0",
+ "America/Bahia_Banderas": "CST6CDT,M4.1.0,M10.5.0",
+ "America/Boa_Vista": "AMT4",
+ "Africa/Tripoli": "EET-2",
+ "Indian/Reunion": "RET-4",
+ "Atlantic/Stanley": "FKST3",
+ "America/Blanc-Sablon": "AST4",
+ "Antarctica/Syowa": "SYOT-3",
+ "America/Jamaica": "EST5",
+ "Europe/Kiev": "EET-2EEST,M3.5.0/3,M10.5.0/4",
+ "Europe/Budapest": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Pacific/Midway": "SST11",
+ "America/Goose_Bay": "AST4ADT,M3.2.0,M11.1.0",
+ "Asia/Amman": "EET-2EEST,M3.5.4/24,M10.5.5/1",
+ "Asia/Sakhalin": "SAKT-11",
+ "Africa/Windhoek": "WAT-1WAST,M9.1.0,M4.1.0",
+ "America/Sitka": "AKST9AKDT,M3.2.0,M11.1.0",
+ "America/Guyana": "GYT4",
+ "Pacific/Pohnpei": "PONT-11",
+ "America/Sao_Paulo": "BRT3BRST,M10.3.0/0,M2.3.0/0",
+ "America/Lower_Princes": "AST4",
+ "Australia/Perth": "WST-8",
+ "Africa/Djibouti": "EAT-3",
+ "Asia/Jakarta": "WIB-7",
+ "Antarctica/Palmer": "CLT4CLST,M9.1.6/24,M4.4.6/24",
+ "Africa/Johannesburg": "SAST-2",
+ "Asia/Irkutsk": "IRKT-9",
+ "Africa/Niamey": "WAT-1",
+ "Africa/Casablanca": "WET0WEST,M3.5.0,M10.5.0/3",
+ "America/Indiana/Marengo": "EST5EDT,M3.2.0,M11.1.0",
+ "Africa/Nouakchott": "GMT0",
+ "Europe/Vilnius": "EET-2EEST,M3.5.0/3,M10.5.0/4",
+ "America/Cayenne": "GFT3",
+ "Africa/Mogadishu": "EAT-3",
+ "America/Kentucky/Monticello": "EST5EDT,M3.2.0,M11.1.0",
+ "America/Rio_Branco": "ACT5",
+ "America/Cancun": "CST6CDT,M4.1.0,M10.5.0",
+ "America/Indiana/Knox": "CST6CDT,M3.2.0,M11.1.0",
+ "America/Havana": "CST5CDT,M3.2.0/0,M11.1.0/1",
+ "Pacific/Guam": "ChST-10",
+ "Pacific/Kosrae": "KOST-11",
+ "Atlantic/Azores": "AZOT1AZOST,M3.5.0/0,M10.5.0/1",
+ "Australia/Eucla": "CWST-8:45",
+ "Asia/Shanghai": "CST-8",
+ "America/Rankin_Inlet": "CST6CDT,M3.2.0,M11.1.0",
+ "Asia/Beirut": "EET-2EEST,M3.5.0/0,M10.5.0/0",
+ "Africa/Maputo": "CAT-2",
+ "Asia/Bahrain": "AST-3",
+ "Asia/Ashgabat": "TMT-5",
+ "Asia/Riyadh": "AST-3",
+ "Europe/London": "GMT0BST,M3.5.0/1,M10.5.0",
+ "America/Monterrey": "CST6CDT,M4.1.0,M10.5.0",
+ "America/Anguilla": "AST4",
+ "Asia/Damascus": "EET-2EEST,M3.5.5/0,M10.5.5/0",
+ "America/North_Dakota/Center": "CST6CDT,M3.2.0,M11.1.0",
+ "America/Indiana/Vevay": "EST5EDT,M3.2.0,M11.1.0",
+ "Atlantic/St_Helena": "GMT0",
+ "America/Barbados": "AST4",
+ "Europe/Vatican": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Atlantic/Faroe": "WET0WEST,M3.5.0/1,M10.5.0",
+ "Asia/Almaty": "ALMT-6",
+ "America/Santo_Domingo": "AST4",
+ "Africa/Brazzaville": "WAT-1",
+ "America/Nome": "AKST9AKDT,M3.2.0,M11.1.0",
+ "Europe/Dublin": "GMT0IST,M3.5.0/1,M10.5.0",
+ "America/Yakutat": "AKST9AKDT,M3.2.0,M11.1.0",
+ "America/Argentina/Mendoza": "ART3",
+ "America/Araguaina": "BRT3",
+ "Europe/Vaduz": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Antarctica/Mawson": "MAWT-5",
+ "Asia/Kolkata": "IST-5:30",
+ "Africa/Maseru": "SAST-2",
+ "America/Atikokan": "EST5",
+ "America/Santa_Isabel": "PST8PDT,M4.1.0,M10.5.0",
+ "Asia/Kuching": "MYT-8",
+ "Africa/Libreville": "WAT-1",
+ "Africa/Freetown": "GMT0",
+ "Africa/Bissau": "GMT0",
+ "Europe/Samara": "SAMT-4",
+ "Europe/Amsterdam": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Europe/Tirane": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Pacific/Saipan": "ChST-10",
+ "Africa/Abidjan": "GMT0",
+ "Europe/Zaporozhye": "EET-2EEST,M3.5.0/3,M10.5.0/4",
+ "America/El_Salvador": "CST6",
+ "Europe/Madrid": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Africa/Juba": "EAT-3",
+ "America/Santiago": "CLT4CLST,M9.1.6/24,M4.4.6/24",
+ "America/Argentina/Buenos_Aires": "ART3",
+ "America/Argentina/San_Luis": "ART3",
+ "Europe/Skopje": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "America/Aruba": "AST4",
+ "America/Regina": "CST6",
+ "Pacific/Chuuk": "CHUT-10",
+ "Asia/Khandyga": "YAKT-10",
+ "Pacific/Funafuti": "TVT-12",
+ "America/Merida": "CST6CDT,M4.1.0,M10.5.0",
+ "America/Guatemala": "CST6",
+ "Africa/Lome": "GMT0",
+ "Africa/Sao_Tome": "GMT0",
+ "Asia/Makassar": "WITA-8",
+ "Africa/Bujumbura": "CAT-2",
+ "Europe/Chisinau": "EET-2EEST,M3.5.0/3,M10.5.0/4",
+ "Europe/Warsaw": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Asia/Yekaterinburg": "YEKT-6",
+ "Antarctica/Casey": "WST-8",
+ "America/Halifax": "AST4ADT,M3.2.0,M11.1.0",
+ "America/Thule": "AST4ADT,M3.2.0,M11.1.0",
+ "America/St_Johns": "NST3:30NDT,M3.2.0,M11.1.0",
+ "America/Moncton": "AST4ADT,M3.2.0,M11.1.0",
+ "Europe/Helsinki": "EET-2EEST,M3.5.0/3,M10.5.0/4",
+ "Atlantic/Cape_Verde": "CVT1",
+ "America/Tegucigalpa": "CST6",
+ "Indian/Cocos": "CCT-6:30",
+ "America/Boise": "MST7MDT,M3.2.0,M11.1.0",
+ "America/Guadeloupe": "AST4",
+ "America/Nassau": "EST5EDT,M3.2.0,M11.1.0",
+ "Europe/Prague": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Pacific/Enderbury": "PHOT-13",
+ "Asia/Hovd": "HOVT-7",
+ "America/Manaus": "AMT4",
+ "America/Godthab": "WGT3WGST,M3.5.0/-2,M10.5.0/-1",
+ "America/North_Dakota/Beulah": "CST6CDT,M3.2.0,M11.1.0",
+ "America/Chihuahua": "MST7MDT,M4.1.0,M10.5.0",
+ "America/Iqaluit": "EST5EDT,M3.2.0,M11.1.0",
+ "America/Argentina/Rio_Gallegos": "ART3",
+ "Pacific/Gambier": "GAMT9",
+ "Europe/Volgograd": "VOLT-4",
+ "Africa/Bamako": "GMT0",
+ "Asia/Novokuznetsk": "NOVT-7",
+ "Europe/Uzhgorod": "EET-2EEST,M3.5.0/3,M10.5.0/4",
+ "Africa/Banjul": "GMT0",
+ "Asia/Aqtau": "AQTT-5",
+ "Africa/Malabo": "WAT-1",
+ "Atlantic/Madeira": "WET0WEST,M3.5.0/1,M10.5.0",
+ "Pacific/Noumea": "NCT-11",
+ "Africa/Kinshasa": "WAT-1",
+ "Europe/Malta": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "America/Argentina/Ushuaia": "ART3",
+ "Asia/Bangkok": "ICT-7",
+ "Pacific/Niue": "NUT11",
+ "Australia/Brisbane": "EST-10",
+ "America/Recife": "BRT3",
+ "Asia/Yerevan": "AMT-4",
+ "America/La_Paz": "BOT4",
+ "Africa/Cairo": "EET-2EEST,M4.5.5/0,M9.5.4/24",
+ "Africa/Lusaka": "CAT-2",
+ "Pacific/Guadalcanal": "SBT-11",
+ "America/Yellowknife": "MST7MDT,M3.2.0,M11.1.0",
+ "Asia/Vientiane": "ICT-7",
+ "Europe/Kaliningrad": "FET-3",
+ "Africa/Conakry": "GMT0",
+ "America/Argentina/Tucuman": "ART3",
+ "Asia/Hebron": "EET-2EEST,M3.5.4/24,M9.3.6/144",
+ "Europe/Oslo": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "America/St_Kitts": "AST4",
+ "America/Panama": "EST5",
+ "Africa/Gaborone": "CAT-2",
+ "Pacific/Palau": "PWT-9",
+ "America/Guayaquil": "ECT5",
+ "Asia/Kuala_Lumpur": "MYT-8",
+ "America/Menominee": "CST6CDT,M3.2.0,M11.1.0",
+ "Asia/Kamchatka": "PETT-12",
+ "Asia/Vladivostok": "VLAT-11",
+ "America/Matamoros": "CST6CDT,M3.2.0,M11.1.0",
+ "Asia/Qatar": "AST-3",
+ "Asia/Dubai": "GST-4",
+ "Asia/Yakutsk": "YAKT-10",
+ "Asia/Omsk": "OMST-7",
+ "Africa/Bangui": "WAT-1",
+ "America/Paramaribo": "SRT3",
+ "Africa/Lubumbashi": "CAT-2",
+ "Pacific/Marquesas": "MART9:30",
+ "Europe/Bratislava": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Asia/Anadyr": "ANAT-12",
+ "America/New_York": "EST5EDT,M3.2.0,M11.1.0",
+ "Pacific/Norfolk": "NFT-11:30",
+ "Pacific/Rarotonga": "CKT10",
+ "America/Dominica": "AST4",
+ "Africa/Porto-Novo": "WAT-1",
+ "Asia/Samarkand": "UZT-5",
+ "Asia/Dushanbe": "TJT-5",
+ "America/Kentucky/Louisville": "EST5EDT,M3.2.0,M11.1.0",
+ "America/Toronto": "EST5EDT,M3.2.0,M11.1.0",
+ "America/Bahia": "BRT3",
+ "Africa/Kampala": "EAT-3",
+ "Africa/Ouagadougou": "GMT0",
+ "Asia/Muscat": "GST-4",
+ "America/Port_of_Spain": "AST4",
+ "Pacific/Wake": "WAKT-12",
+ "America/Indiana/Tell_City": "CST6CDT,M3.2.0,M11.1.0",
+ "Australia/Darwin": "CST-9:30",
+ "America/Whitehorse": "PST8PDT,M3.2.0,M11.1.0",
+ "America/Swift_Current": "CST6",
+ "Europe/Copenhagen": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "America/Argentina/Salta": "ART3",
+ "America/Montserrat": "AST4",
+ "Europe/Simferopol": "MSK-4",
+ "Africa/Blantyre": "CAT-2",
+ "America/Detroit": "EST5EDT,M3.2.0,M11.1.0",
+ "America/Grenada": "AST4",
+ "America/Indiana/Vincennes": "EST5EDT,M3.2.0,M11.1.0",
+ "America/Indiana/Petersburg": "EST5EDT,M3.2.0,M11.1.0",
+ "Asia/Kathmandu": "NPT-5:45",
+ "Asia/Pontianak": "WIB-7",
+ "Africa/Dar_es_Salaam": "EAT-3",
+ "America/Port-au-Prince": "EST5EDT,M3.2.0,M11.1.0",
+ "America/Cayman": "EST5",
+ "Europe/Athens": "EET-2EEST,M3.5.0/3,M10.5.0/4",
+ "America/Curacao": "AST4",
+ "Indian/Kerguelen": "TFT-5",
+ "Africa/Khartoum": "EAT-3",
+ "Asia/Manila": "PHT-8",
+ "Europe/Sarajevo": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Africa/Douala": "WAT-1",
+ "Europe/Rome": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "America/Argentina/San_Juan": "ART3",
+ "America/North_Dakota/New_Salem": "CST6CDT,M3.2.0,M11.1.0",
+ "America/Kralendijk": "AST4",
+ "Pacific/Port_Moresby": "PGT-10",
+ "Europe/Jersey": "GMT0BST,M3.5.0/1,M10.5.0",
+ "Europe/Andorra": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Europe/Luxembourg": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Pacific/Honolulu": "HST10",
+ "America/St_Thomas": "AST4",
+ "Pacific/Majuro": "MHT-12",
+ "America/Mazatlan": "MST7MDT,M4.1.0,M10.5.0",
+ "Asia/Macau": "CST-8",
+ "Europe/Belgrade": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Asia/Choibalsan": "CHOT-8",
+ "Europe/Mariehamn": "EET-2EEST,M3.5.0/3,M10.5.0/4",
+ "Antarctica/McMurdo": "NZST-12NZDT,M9.5.0,M4.1.0/3",
+ "America/Thunder_Bay": "EST5EDT,M3.2.0,M11.1.0",
+ "America/Los_Angeles": "PST8PDT,M3.2.0,M11.1.0",
+ "Asia/Kabul": "AFT-4:30",
+ "Indian/Antananarivo": "EAT-3",
+ "Atlantic/Reykjavik": "GMT0",
+ "Asia/Nicosia": "EET-2EEST,M3.5.0/3,M10.5.0/4",
+ "Pacific/Tongatapu": "TOT-13",
+ "America/Marigot": "AST4",
+ "Pacific/Pitcairn": "PST8",
+ "Pacific/Easter": "EAST6EASST,M9.1.6/22,M4.4.6/22",
+ "Atlantic/South_Georgia": "GST2",
+ "Africa/El_Aaiun": "WET0WEST,M3.5.0,M10.5.0/3",
+ "America/Campo_Grande": "AMT4AMST,M10.3.0/0,M2.3.0/0",
+ "America/Dawson_Creek": "MST7",
+ "Antarctica/Vostok": "VOST-6",
+ "Europe/Bucharest": "EET-2EEST,M3.5.0/3,M10.5.0/4",
+ "America/Porto_Velho": "AMT4",
+ "Europe/Monaco": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Asia/Bishkek": "KGT-6",
+ "Africa/Ceuta": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "America/Winnipeg": "CST6CDT,M3.2.0,M11.1.0",
+ "Asia/Aqtobe": "AQTT-5",
+ "Africa/Dakar": "GMT0",
+ "America/Fortaleza": "BRT3",
+ "Pacific/Tarawa": "GILT-12",
+ "America/Dawson": "PST8PDT,M3.2.0,M11.1.0",
+ "Africa/Addis_Ababa": "EAT-3",
+ "Pacific/Efate": "VUT-11",
+ "Pacific/Johnston": "HST10",
+ "Asia/Qyzylorda": "QYZT-6",
+ "Europe/San_Marino": "CET-1CEST,M3.5.0,M10.5.0/3",
+ "Asia/Jerusalem": "IST-2IDT,M3.4.4/26,M10.5.0",
+ "Pacific/Auckland": "NZST-12NZDT,M9.5.0,M4.1.0/3",
+ "America/Metlakatla": "MeST8",
+ "America/Tortola": "AST4",
+ "America/Denver": "MST7MDT,M3.2.0,M11.1.0",
+ "Indian/Chagos": "IOT-6",
+ "America/Glace_Bay": "AST4ADT,M3.2.0,M11.1.0",
+ "America/Hermosillo": "MST7",
+ "Africa/Tunis": "CET-1",
+ "America/Montevideo": "UYT3UYST,M10.1.0,M3.2.0",
+ "Asia/Ust-Nera": "VLAT-11",
+ "America/Resolute": "CST6CDT,M3.2.0,M11.1.0",
+ "Asia/Gaza": "EET-2EEST,M3.5.4/24,M9.3.6/144",
+ "Asia/Taipei": "CST-8",
+ "Antarctica/DumontDUrville": "DDUT-10",
+ "America/Argentina/Catamarca": "ART3",
+ "Antarctica/Troll": "UTC0CEST-2,M3.5.0/1,M10.5.0/3",
+ "Asia/Novosibirsk": "NOVT-7",
+ "Africa/Kigali": "CAT-2",
+ "America/Grand_Turk": "EST5EDT,M3.2.0,M11.1.0",
+ "Africa/Lagos": "WAT-1",
+ "Europe/Sofia": "EET-2EEST,M3.5.0/3,M10.5.0/4",
+ "America/Lima": "PET5",
+ "America/Anchorage": "AKST9AKDT,M3.2.0,M11.1.0",
+ "Pacific/Nauru": "NRT-12",
+}
diff --git a/routerapi/update b/routerapi/update
index 5e0827e..ef9f4de 100755
--- a/routerapi/update
+++ b/routerapi/update
@@ -14,6 +14,9 @@ try:
ret = "update-success" # Should never reach this line of code
else:
ret = "update-failure"
+except OSError:
+ # catch call-errors and return error message
+ pass
finally:
nullfile.close()
diff --git a/routerapi/update_setting b/routerapi/update_setting
index 5ce1c1c..ac5a663 100755
--- a/routerapi/update_setting
+++ b/routerapi/update_setting
@@ -5,9 +5,9 @@ import sys
import common
import uci
+import accumulate_bytes
environ = os.environ
-params = {}
band_5_channel_options = ['auto',
'36 (5.180 GHz)', '40 (5.200 GHz)', '44 (5.220 GHz)', '48 (5.240 GHz)',
'149 (5.745 GHz)', '153 (5.765 GHz)', '159 (5.785 GHz)', '161 (5.805 GHz)',
@@ -37,30 +37,30 @@ def set_param(device, param, value):
uci.commit("wireless")
def set_error(param):
- params['error'] = 'Invalid ' + param
+ raise Exception('Invalid ' + param)
def check_band(band_name, interface_name):
- if params.get(band_name):
- if params.get(band_name) in ["2.4", "5"]:
- current_band = check_device(interface_name)
+ if band_name:
+ if band_name in ["2.4", "5"]:
+ current_band = check_device(interface_name)
- if current_band == "radio0":
- new_band = "radio1"
+ if current_band == "radio0":
+ new_band = "radio1"
- else:
- new_band = "radio0"
+ else:
+ new_band = "radio0"
- if new_band != check_param(interface_name, "device"):
- set_param(interface_name, "device", new_band)
- common.reset_wifi()
+ if new_band != check_param(interface_name, "device"):
+ set_param(interface_name, "device", new_band)
+ common.reset_wifi()
- else:
- set_error('band')
+ else:
+ set_error('band')
def check_channel(channel_name, interface_name):
- if params.get(channel_name):
+ if channel_name:
current_device = check_device(interface_name)
- new_channel = params.get(channel_name)
+ new_channel = channel_name
if validate_channel(current_device, new_channel):
if new_channel.split(' ')[0] != check_param(current_device, 'channel'):
set_param(current_device, 'channel', new_channel.split(' ')[0])
@@ -70,9 +70,9 @@ def check_channel(channel_name, interface_name):
set_error('channel')
def check_channel_bandwidth(channel_name, interface_name):
- if params.get(channel_name):
+ if channel_name:
current_device = check_device(interface_name)
- new_bandwidth = params.get(channel_name)
+ new_bandwidth = channel_name
if validate_bandwidth(new_bandwidth):
if check_param(current_device, 'htmode') != "HT" + new_bandwidth:
set_param(current_device, 'htmode', "HT" + new_bandwidth)
@@ -88,57 +88,61 @@ def set_openwireless_use_limit(option):
uci.set(openwireless_interface, str(int(openwireless_bandwidth)))
uci.commit("sqm")
-def check_openwireless_bandwidth_percentage():
- if (params.get("openwirelessBandwidth")):
- new_percentage = params.get("openwirelessBandwidth")
-
- uci.set("openwireless.maxbandwidthpercentage", new_percentage)
+def check_openwireless_bandwidth_percentage(percentage):
+ if percentage:
+ uci.set("openwireless.maxbandwidthpercentage", percentage)
uci.commit("openwireless")
set_openwireless_use_limit("download")
set_openwireless_use_limit("upload")
-def check_isp_upload_speed():
- if (params.get("ispUploadSpeed")):
- new_speed = float(params.get("ispUploadSpeed"))
- new_speed_kbs = str(int(new_speed * 1000))
- uci.set("sqm.ge00.upload", new_speed_kbs)
+def check_isp_upload_speed(speed):
+ if speed:
+ speed_kbs = str(int(float(speed) * 1000))
+ uci.set("sqm.ge00.upload", speed_kbs)
uci.commit("sqm")
set_openwireless_use_limit("upload")
-def check_isp_download_speed():
- if (params.get("ispDownloadSpeed")):
- new_speed = float(params.get("ispDownloadSpeed"))
- new_speed_kbs = str(int(new_speed * 1000))
- uci.set("sqm.ge00.download", new_speed_kbs)
+def check_isp_download_speed(speed):
+ if speed:
+ speed_kbs = str(int(float(speed) * 1000))
+ uci.set("sqm.ge00.download", speed_kbs)
uci.commit("sqm")
set_openwireless_use_limit("download")
-def check_openwireless_monthly_data():
- if (params.get("openwirelessData")):
- new_bandwidth = params.get("openwirelessData")
- uci.set("openwireless.maxmonthlybandwidth", new_bandwidth)
- uci.commit("openwireless")
+def check_openwireless_monthly_data(bandwidth):
+ if bandwidth:
+ uci.set("openwireless.maxmonthlybandwidth", bandwidth)
+ uci.commit("openwireless")
+ accumulate_bytes.update_network_availability()
+def do_post(params):
+ check_band(params.get('routerBand'), "@wifi-iface[2]")
+ check_channel(params.get('routerChannel'), "@wifi-iface[2]")
+ check_channel_bandwidth(params.get('routerChannelBandwidth'), "@wifi-iface[2]")
+ check_band(params.get('openwirelessBand'), "@wifi-iface[1]")
+ check_channel(params.get('openwirelessChannel'), "@wifi-iface[1]")
+ check_channel_bandwidth(params.get('openwirelessChannelBandwidth'), "@wifi-iface[1]")
-if environ.get('REQUEST_METHOD').lower() == 'post':
- params = json.loads(sys.stdin.read())
+ check_isp_upload_speed(params.get("ispUploadSpeed"))
+ check_isp_download_speed(params.get("ispDownloadSpeed"))
- check_band('routerBand', "@wifi-iface[2]")
- check_channel('routerChannel', "@wifi-iface[2]")
- check_channel_bandwidth('routerChannelBandwidth', "@wifi-iface[0]")
+ check_openwireless_bandwidth_percentage(params.get("openwirelessBandwidth"))
- check_band('openwirelessBand', "@wifi-iface[1]")
- check_channel('openwirelessChannel', "@wifi-iface[1]")
- check_channel_bandwidth('openwirelessChannelBandwidth', "@wifi-iface[1]")
+ check_openwireless_monthly_data(params.get("openwirelessData"))
- check_isp_upload_speed()
- check_isp_download_speed()
- check_openwireless_bandwidth_percentage()
- check_openwireless_monthly_data()
-else:
- set_error('GET request')
+def main():
+ try:
+ if environ.get('REQUEST_METHOD').lower() == 'post':
+ params = json.loads(sys.stdin.read())
+ do_post(params)
+ else:
+ raise Exception('GET request')
+ common.render_success(params)
+ except Exception as e:
+ common.render_error(str.join(' ', e.args), status = 500)
-common.render_success(params)
+if __name__ == '__main__':
+ main()
diff --git a/scripts/build-with-image-builder b/scripts/build-with-image-builder
new file mode 100755
index 0000000..efb105e
--- /dev/null
+++ b/scripts/build-with-image-builder
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+set -e
+set -x
+
+ROOT=$(cd `dirname $0`/.. && pwd)
+CACHE=$ROOT/.cache
+TARGET=`mktemp -d /tmp/openwireless-XXXX`/target
+IMAGE_BUILDER=OpenWrt-ImageBuilder-ar71xx_generic-for-linux-x86_64
+IMAGE_BUILDER_URL=http://snapon.lab.bufferbloat.net/~cero2/cerowrt/wndr/3.10.50-1/$IMAGE_BUILDER.tar.bz2
+IMAGE_BUILDER_ARTIFACT=$IMAGE_BUILDER.tar.bz2
+REPOSITORIES_CONF=$ROOT/infra/repositories.conf
+FILES=$TARGET/files
+
+rm -Rf $TARGET
+mkdir -p $TARGET
+mkdir -p $CACHE
+if [ ! -f $CACHE/$IMAGE_BUILDER_ARTIFACT ]; then
+ curl -o $CACHE/$IMAGE_BUILDER_ARTIFACT $IMAGE_BUILDER_URL
+fi
+cp $CACHE/$IMAGE_BUILDER_ARTIFACT $TARGET
+cd $TARGET
+tar xf $IMAGE_BUILDER_ARTIFACT
+cd $ROOT
+cp $REPOSITORIES_CONF $TARGET/$IMAGE_BUILDER
+
+mkdir -p $FILES
+
+cp -rp $ROOT/etc $FILES/
+
+$ROOT/scripts/template $ROOT/lighttpd/lighttpd.conf.template > $FILES/etc/lighttpd/lighttpd.conf < $ROOT/lighttpd/router.properties
+
+cp -rp $ROOT/lib $FILES/
+
+mkdir $FILES/www
+
+cp -rp $ROOT/app/* $FILES/www/
+
+mkdir $FILES/www/cgi-bin
+
+cp -rp $ROOT/routerapi $FILES/www/cgi-bin/
+
+cd $TARGET/$IMAGE_BUILDER
+
+rmdir dl
+ln -s $CACHE dl
+
+make image PROFILE=WNDR3700 PACKAGES="dropbear lighttpd lighttpd-mod-alias lighttpd-mod-cgi lighttpd-mod-expire lighttpd-mod-redirect lighttpd-mod-setenv lighttpd-mod-simple-vhost python sudo sqm-scripts rsync 6in4 6rd 6to4 ahcpd avahi-daemon block-mount ca-certificates chat comgt curl dbus ddns-scripts dnsmasq-full dropbear-xinetd ds-lite e2fsprogs etherwake ethtool fping gnupg hd-idle hostapd hostapd-utils ip ip-full ip6tables-mod-nat ipset iptables-mod-account iptables-mod-extra iptables-mod-ipmark iptables-mod-u32 iptaccount kmod-8021q kmod-ath9k-htc kmod-atm kmod-crypto-authenc kmod-crypto-hash kmod-crypto-manager kmod-crypto-pcompress kmod-fs-autofs4 kmod-fs-ext4 kmod-fs-vfat kmod-gre kmod-ip6-tunnel kmod-ipip kmod-ipt-account kmod-ipt-compat-xtables kmod-ipt-extra kmod-ipt-hashlimit kmod-ipt-ipmark kmod-ipt-ipset kmod-ipt-nat6 kmod-ipt-u32 kmod-iptunnel kmod-iptunnel4 kmod-iptunnel6 kmod-leds-gpio kmod-ledtrig-default-on kmod-ledtrig-netdev kmod-ledtrig-timer kmod-lib-crc16 kmod-libphy kmod-mii kmod-nat46 kmod-nf-conntrack-netlink kmod-nfnetlink kmod-nls-cp437 kmod-nls-iso8859-1 kmod-nls-iso8859-13 kmod-nls-iso8859-15 kmod-nls-iso8859-2 kmod-pppoa kmod-pptp kmod-scsi-cdrom kmod-scsi-core kmod-sit kmod-swconfig kmod-usb-net kmod-usb-storage lft libavahi libavahi-dbus-support libblkid libcurl libdaemon libdbus libelf1 libevent2 libexpat libext2fs libgmp libgpg-error libiwinfo libmnl libmount libncurses libncursesw libnetfilter-conntrack libnettle libnfnetlink libpcap libpolarssl libpopt libreadline librt libuuid lighttpd-mod-fastcgi linux-atm miniupnpd mount-utils ntpclient ohybridproxy openssl-util opkg-smime ppp-mod-pppoa px5g python-curl relayd rng-tools rsync tcpdump-mini terminfo time tor wireless-tools wol xinetd zile" FILES=$FILES
+
+mkdir -p $ROOT/dist
+rm -Rf $ROOT/dist/*
+cp -R $TARGET/$IMAGE_BUILDER/bin/* $ROOT/dist
diff --git a/scripts/pre-commit b/scripts/pre-commit
new file mode 100755
index 0000000..415d2a6
--- /dev/null
+++ b/scripts/pre-commit
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+set -ex
+
+ROOT=`pwd`
+USE_VAGRANT=`ls .vagrant &> /dev/null && test $(whoami) != "vagrant"; echo $?`
+COMMAND="./run-tests.sh"
+
+if [ "$USE_VAGRANT" -eq "0" ]; then
+ vagrant ssh -c "cd /vagrant && $COMMAND"
+else
+ $COMMAND
+fi
diff --git a/scripts/template b/scripts/template
new file mode 100755
index 0000000..1aadab3
--- /dev/null
+++ b/scripts/template
@@ -0,0 +1,10 @@
+#!/usr/bin/env python2.7
+
+import sys
+
+replacements = dict(i.strip().split('=') for i in sys.stdin.readlines())
+
+filename = sys.argv[1]
+
+with open(filename) as template:
+ print template.read() % replacements
diff --git a/scripts/unit b/scripts/unit
new file mode 100755
index 0000000..4ac60bd
--- /dev/null
+++ b/scripts/unit
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+set -e
+
+/usr/bin/env python2.7 -m unittest discover -s test/ -p '*_test.py'
diff --git a/sendToBuild b/sendToBuild
index 92497e6..669d642 100755
--- a/sendToBuild
+++ b/sendToBuild
@@ -28,3 +28,5 @@ mkdir cerowrt/files/www/cgi-bin
echo "pushing routerapi to build..."
cp -rp routerapi cerowrt/files/www/cgi-bin/
+echo "building lighttpd config..."
+cat lighttpd/router.properties | scripts/template lighttpd/lighttpd.conf.template > cerowrt/files/etc/lighttpd/lighttpd.conf
diff --git a/test/accumulate_bytes_test.py b/test/accumulate_bytes_test.py
new file mode 100644
index 0000000..066efac
--- /dev/null
+++ b/test/accumulate_bytes_test.py
@@ -0,0 +1,66 @@
+import unittest
+import mock
+import sys
+import os
+
+sys.path.insert(0, os.path.join(
+ os.path.dirname(os.path.realpath(__file__)),
+ "..", "routerapi"))
+
+import accumulate_bytes
+from fake_uci import FakeUci
+
+@mock.patch('accumulate_bytes.common.reset_wifi')
+@mock.patch('accumulate_bytes.uci', new_callable = FakeUci)
+class AccumulateBytesTest(unittest.TestCase):
+ def with_usage_in_mb(self, uci, usage):
+ uci.set("openwireless.use_before_last_reset", "0")
+ uci.set("openwireless.use_since_last_reset", float(usage) * 1024 * 1024)
+ uci.set("openwireless.use_at_last_ui_reset", "0")
+ uci.commit("openwireless")
+
+ def test_turn_on_adapter_if_off_and_sufficient_bandwidth(self, uci, reset):
+ uci.set("openwireless.maxmonthlybandwidth", "20")
+ uci.set("wireless.@wifi-iface[1].disabled", "1")
+ self.with_usage_in_mb(uci, "0")
+ uci.commit("openwireless")
+ uci.commit("wireless")
+
+ accumulate_bytes.update_network_availability()
+
+ self.assertEquals(uci.get("wireless.@wifi-iface[1].disabled"), "0")
+ reset.assert_called_with()
+
+ def test_turn_off_adapter_if_on_and_insufficient_bandwidth(self, uci, reset):
+ self.with_usage_in_mb(uci, "20")
+ uci.set("openwireless.maxmonthlybandwidth", "20")
+ uci.set("wireless.@wifi-iface[1].disabled", "0")
+ uci.commit("openwireless")
+ uci.commit("wireless")
+
+ accumulate_bytes.update_network_availability()
+
+ self.assertEquals(uci.get("wireless.@wifi-iface[1].disabled"), "1")
+ reset.assert_called_with()
+
+ def test_do_not_reset_when_not_changing_on_state(self, uci, reset):
+ self.with_usage_in_mb(uci, "20")
+ uci.set("openwireless.maxmonthlybandwidth", "40")
+ uci.set("wireless.@wifi-iface[1].disabled", "0")
+ uci.commit("openwireless")
+ uci.commit("wireless")
+
+ accumulate_bytes.update_network_availability()
+
+ self.assertFalse(reset.called)
+
+ def test_do_not_reset_when_not_changing_off_state(self, uci, reset):
+ self.with_usage_in_mb(uci, "20")
+ uci.set("openwireless.maxmonthlybandwidth", "10")
+ uci.set("wireless.@wifi-iface[1].disabled", "1")
+ uci.commit("openwireless")
+ uci.commit("wireless")
+
+ accumulate_bytes.update_network_availability()
+
+ self.assertFalse(reset.called)
diff --git a/test/auth_test.py b/test/auth_test.py
index 6fd5dcc..e898305 100644
--- a/test/auth_test.py
+++ b/test/auth_test.py
@@ -58,6 +58,8 @@ def test_password(self):
self.assertTrue(os.path.isfile(os.path.join(self.path, "password")))
self.assertTrue(self.auth.is_password("Passw0rd"))
self.assertFalse(self.auth.is_password("badpass"))
+ self.assertFalse(self.auth.save_password("2Short"))
+ self.assertTrue(self.auth.is_password("Passw0rd"))
def test_write(self):
filename = os.path.join(self.path, "foo")
diff --git a/test/fake_uci.py b/test/fake_uci.py
new file mode 100644
index 0000000..b860e5b
--- /dev/null
+++ b/test/fake_uci.py
@@ -0,0 +1,18 @@
+class FakeUci:
+ def __init__(self, data={}):
+ self.data = data
+ self.tmp = {}
+
+ def get(self, name):
+ return self.data[name]
+
+ def set(self, name, value):
+ self.tmp[name] = value
+
+ def commit(self, section):
+ match = lambda x: x[0].startswith(section + ".")
+ tmp_section_items = [i for i in self.tmp.items() if match(i)]
+ non_tmp_section_items = [i for i in self.tmp.items() if not match(i)]
+
+ self.data = dict(self.data.items() + tmp_section_items)
+ self.tmp = dict(non_tmp_section_items)
diff --git a/test/fake_uci_test.py b/test/fake_uci_test.py
new file mode 100644
index 0000000..f98a787
--- /dev/null
+++ b/test/fake_uci_test.py
@@ -0,0 +1,46 @@
+import unittest
+
+from fake_uci import FakeUci
+
+class FakeUciTest(unittest.TestCase):
+ def test_get_when_key_exists(self):
+ uci = FakeUci(data = {'section.key': 1})
+
+ self.assertEquals(1, uci.get('section.key'))
+
+ def test_get_when_key_missing(self):
+ uci = FakeUci(data = {})
+
+ self.assertRaises(KeyError, uci.get, ('section.key'))
+
+ def test_set_without_commit(self):
+ uci = FakeUci()
+
+ uci.set('section.key', 1)
+
+ self.assertRaises(KeyError, uci.get, ('section.key'))
+
+ def test_set_with_commit(self):
+ uci = FakeUci()
+
+ uci.set('section.key', 1)
+ uci.commit('section')
+
+ self.assertEquals(1, uci.get('section.key'))
+
+ def test_set_with_commit_on_different_section(self):
+ uci = FakeUci()
+
+ uci.set('section.key', 1)
+ uci.commit('section1')
+
+ self.assertRaises(KeyError, uci.get, ('section.key'))
+
+ def test_set_with_commit_on_section_after_commit_on_different_section(self):
+ uci = FakeUci()
+
+ uci.set('section.key', 1)
+ uci.commit('section1')
+ uci.commit('section')
+
+ self.assertEquals(1, uci.get('section.key'))
diff --git a/test/gen_tz_dictionary_test.py b/test/gen_tz_dictionary_test.py
new file mode 100644
index 0000000..4bc7193
--- /dev/null
+++ b/test/gen_tz_dictionary_test.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python2.7
+
+import unittest, sys, os
+
+sys.path.insert(0, os.path.join(
+ os.path.dirname(os.path.realpath(__file__)),
+ "..", "routerapi"))
+
+import gen_tz_dictionary
+
+class genTzDictionaryTest(unittest.TestCase):
+
+ def test_get_zone_info(self):
+ tzd = gen_tz_dictionary.get_zone_info()
+ self.assertTrue(type(tzd) is dict)
+ self.assertTrue(len(tzd) > 1)
+ self.assertEqual(tzd["America/Los_Angeles"], "PST8PDT,M3.2.0,M11.1.0")
+
+ self.assertFalse(gen_tz_dictionary.get_zone_info("/does/not/exist"))
+
+
+ def test_read_posix_zone(self):
+ posix_zone = gen_tz_dictionary.read_posix_zone("America/Los_Angeles")
+ self.assertEqual(posix_zone, "PST8PDT,M3.2.0,M11.1.0")
+
+ with self.assertRaises(EnvironmentError):
+ gen_tz_dictionary.read_posix_zone("Fake/Zone")
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/test/set_timezone_test.py b/test/set_timezone_test.py
index 4b0b815..d9fe120 100644
--- a/test/set_timezone_test.py
+++ b/test/set_timezone_test.py
@@ -29,7 +29,7 @@ def tearDown(self):
sys.stdin = self.saved_stdin
def test_set_timezone(self):
- setInput('{"jsonrpc":"2.0","method":"set_timezone","params":["EFF0local"],"id":1}')
+ setInput('{"jsonrpc":"2.0","method":"set_timezone","params":["America/Los_Angeles"],"id":1}')
with self.assertRaises(SystemExit):
jsonrpc_set_timezone(".")
@@ -37,7 +37,7 @@ def test_set_timezone(self):
with open(TZ_PATH, "r") as tz_file:
tz_data = tz_file.read()
- self.assertEqual(tz_data, "EFF0local")
+ self.assertEqual(tz_data, "PST8PDT,M3.2.0,M11.1.0")
if __name__ == '__main__':
unittest.main()
diff --git a/test/update_setting_test.py b/test/update_setting_test.py
new file mode 100644
index 0000000..da14de0
--- /dev/null
+++ b/test/update_setting_test.py
@@ -0,0 +1,27 @@
+import unittest
+import sys
+import os
+import mock
+from fake_uci import FakeUci
+
+sys.path.insert(0, os.path.join(
+ os.path.dirname(os.path.realpath(__file__)),
+ "..", "routerapi"))
+
+import update_setting
+
+class TestUpdateSetting(unittest.TestCase):
+ @mock.patch('accumulate_bytes.update_network_availability')
+ @mock.patch('update_setting.uci', new_callable = FakeUci)
+ def test_update_network_availability_after_monthly_data_limit_change(self, _, update_network_availability):
+ update_setting.check_openwireless_monthly_data('500')
+ update_network_availability.assert_called_with()
+
+ @mock.patch('accumulate_bytes.update_network_availability')
+ @mock.patch('update_setting.uci', new_callable = FakeUci)
+ def test_update_openwireless_monthly_data(self, uci, _):
+ update_setting.check_openwireless_monthly_data('500')
+
+ bandwidth = uci.get("openwireless.maxmonthlybandwidth")
+ self.assertEquals(bandwidth, '500')
+