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: LoadingLAN 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 \n \n
\n "; + + "
\n
\n \n \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}}
- - +
+ + +
{{/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') +