From e3cf86cc7677df7837e804089d7f73fce19cd4f5 Mon Sep 17 00:00:00 2001
From: Cooper Quintin
Date: Tue, 12 Aug 2014 10:31:54 -0700
Subject: [PATCH 01/54] adding python library to generate Olson to Posix
timezone dictionary
---
routerapi/genTzDictionary.py | 85 +++++++
routerapi/tz_info.py | 423 +++++++++++++++++++++++++++++++++++
2 files changed, 508 insertions(+)
create mode 100644 routerapi/genTzDictionary.py
create mode 100644 routerapi/tz_info.py
diff --git a/routerapi/genTzDictionary.py b/routerapi/genTzDictionary.py
new file mode 100644
index 0000000..50c6af9
--- /dev/null
+++ b/routerapi/genTzDictionary.py
@@ -0,0 +1,85 @@
+#!/usr/bin/python
+"""
+genTzDictionary - 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():
+ """
+ get_zone_info - parse zone info from zoneinfo database into
+ a python dictionary
+ """
+ tzd = {}
+ try:
+ with open(os.path.join(TZ_DB, "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
+ sep = re.compile("\s+")
+ zone = sep.split(line)[2]
+
+ try:
+ tzd[zone] = read_posix_zone(zone)
+ except EnvironmentError: #IOError or OSError
+ continue
+
+ return tzd
+
+ except EnvironmentError:
+ 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 genTzDictionary.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/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",
+}
From d919aba69d187188c5f7f809a56706e8318a7c77 Mon Sep 17 00:00:00 2001
From: Cooper Quintin
Date: Tue, 12 Aug 2014 10:32:25 -0700
Subject: [PATCH 02/54] look up posix timezone in dictionary from olson tz
---
routerapi/set_timezone | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/routerapi/set_timezone b/routerapi/set_timezone
index 866cf59..5c759a2 100755
--- a/routerapi/set_timezone
+++ b/routerapi/set_timezone
@@ -4,22 +4,23 @@ import os
import sys
import common
+from tz_info import tz_info
TZ_PATH = "/etc/TZ"
def jsonrpc_set_timezone(tz_path=TZ_PATH):
- """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:
From ff4629cef8247df7cffc69175bbb856265efa270 Mon Sep 17 00:00:00 2001
From: Cooper Quintin
Date: Tue, 12 Aug 2014 10:32:49 -0700
Subject: [PATCH 03/54] include js library to get olson timezone
---
app/changePassword.html | 1 +
app/lib/jstz-1.0.4.min.js | 2 ++
2 files changed, 3 insertions(+)
create mode 100644 app/lib/jstz-1.0.4.min.js
diff --git a/app/changePassword.html b/app/changePassword.html
index 750b0af..e0a6503 100644
--- a/app/changePassword.html
+++ b/app/changePassword.html
@@ -5,6 +5,7 @@
+
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
Date: Tue, 12 Aug 2014 10:37:07 -0700
Subject: [PATCH 04/54] send olson timezone to python api
---
app/js/changePassword.js | 15 +--------------
1 file changed, 1 insertion(+), 14 deletions(-)
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,
From 65009f28478beacf9efa6a38e9ec65ab56d06263 Mon Sep 17 00:00:00 2001
From: Cooper Quintin
Date: Tue, 12 Aug 2014 10:45:20 -0700
Subject: [PATCH 05/54] updating test
---
test/set_timezone_test.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/set_timezone_test.py b/test/set_timezone_test.py
index 4a44d40..775c2b0 100644
--- a/test/set_timezone_test.py
+++ b/test/set_timezone_test.py
@@ -28,7 +28,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(TZ_PATH)
@@ -36,7 +36,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()
From 5061544abc81f3a03a0ad9501faca1b2ed770434 Mon Sep 17 00:00:00 2001
From: Cooper Quintin
Date: Tue, 12 Aug 2014 10:47:56 -0700
Subject: [PATCH 06/54] rename to snake case
---
routerapi/{genTzDictionary.py => gen_tz_dictionary.py} | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
rename routerapi/{genTzDictionary.py => gen_tz_dictionary.py} (93%)
diff --git a/routerapi/genTzDictionary.py b/routerapi/gen_tz_dictionary.py
similarity index 93%
rename from routerapi/genTzDictionary.py
rename to routerapi/gen_tz_dictionary.py
index 50c6af9..a56e59e 100644
--- a/routerapi/genTzDictionary.py
+++ b/routerapi/gen_tz_dictionary.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
"""
-genTzDictionary - Generate a python file containing a dictionary that maps
+gen_tz_dictionary - Generate a python file containing a dictionary that maps
Olson Time Zones to their POSIX equivalents.
"""
@@ -68,7 +68,7 @@ def write_zone_file(tz_dict):
"""
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 genTzDictionary.py\n\"\"\"\n"
+ "\"\"\"\ntz_info - maps Olson time zones to POSIX equivalents\nAutogenerated by gen_tz_dictionary.py\n\"\"\"\n"
"tz_info = {\n")
footer = "}\n"
From d78e43cb32cdeeb062b38d01400e19de667c026c Mon Sep 17 00:00:00 2001
From: Cooper Quintin
Date: Tue, 12 Aug 2014 11:05:07 -0700
Subject: [PATCH 07/54] tests for gen_tz_dictionary
---
routerapi/gen_tz_dictionary.py | 6 +++---
test/gen_tz_dictionary_test.py | 32 ++++++++++++++++++++++++++++++++
2 files changed, 35 insertions(+), 3 deletions(-)
create mode 100644 test/gen_tz_dictionary_test.py
diff --git a/routerapi/gen_tz_dictionary.py b/routerapi/gen_tz_dictionary.py
index a56e59e..7cacd82 100644
--- a/routerapi/gen_tz_dictionary.py
+++ b/routerapi/gen_tz_dictionary.py
@@ -22,14 +22,14 @@ def generate_dictionary_file():
exit(1)
-def get_zone_info():
+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(TZ_DB, "zone.tab"), "r") as zonetab:
+ 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):
@@ -47,7 +47,7 @@ def get_zone_info():
return tzd
except EnvironmentError:
- return false
+ return False
def read_posix_zone(zone):
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()
+
From 9ae5099779111c0318e275c952cd563b8de86aab Mon Sep 17 00:00:00 2001
From: Cooper Quintin
Date: Wed, 13 Aug 2014 15:57:46 -0700
Subject: [PATCH 08/54] style nits
---
routerapi/gen_tz_dictionary.py | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/routerapi/gen_tz_dictionary.py b/routerapi/gen_tz_dictionary.py
index 7cacd82..859c157 100644
--- a/routerapi/gen_tz_dictionary.py
+++ b/routerapi/gen_tz_dictionary.py
@@ -18,7 +18,7 @@ def generate_dictionary_file():
write_zone_file(get_zone_info())
exit(0)
- #exit with error status if we couldn't read zone info
+ # Exit with error status if we couldn't read zone info
exit(1)
@@ -31,22 +31,21 @@ def get_zone_info(zone_dir=TZ_DB):
try:
with open(os.path.join(zone_dir, "zone.tab"), "r") as zonetab:
for line in zonetab:
- #skip comments and whitespace
+ # Skip comments and whitespace
if re.match("^#", line) or re.match("^\s+$", line):
continue
- #olson zone paths are the third column in the table
- sep = re.compile("\s+")
- zone = sep.split(line)[2]
+ # 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
+ except EnvironmentError: # IOError or OSError
continue
return tzd
- except EnvironmentError:
+ except EnvironmentError: # IOError or OSError
return False
@@ -56,7 +55,7 @@ def read_posix_zone(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 last line of file
return list(zonefile)[-1].rstrip()
From 2a0ad20d6057a7a2455b167a47f8d5cb7a660374 Mon Sep 17 00:00:00 2001
From: Scott Arciszewski
Date: Sat, 4 Oct 2014 17:20:38 -0400
Subject: [PATCH 09/54] Update diceware.js
Prevent whitespace bugs
---
app/js/diceware.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/js/diceware.js b/app/js/diceware.js
index cd3be2d..5bd6257 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]
From 8075811b59bab6e4f4c79879e4787b24cdbb260d Mon Sep 17 00:00:00 2001
From: Scott Arciszewski
Date: Mon, 6 Oct 2014 11:20:57 -0400
Subject: [PATCH 10/54] Update diceware.js
---
app/js/diceware.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/js/diceware.js b/app/js/diceware.js
index 5bd6257..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 = /^\s*?\d+\s*([^\s]+)\s*?$/;
+ var myregexp = /^\s*\d+\s*([^\s]+)\s*$/;
var match = myregexp.exec(line);
if (match != null) {
// matched text: match[0]
From 70970de1a14d05edf0537b0be504783b95af41a7 Mon Sep 17 00:00:00 2001
From: jsha
Date: Wed, 29 Oct 2014 17:29:09 -0700
Subject: [PATCH 11/54] Update README.md
---
README.md | 28 ----------------------------
1 file changed, 28 deletions(-)
diff --git a/README.md b/README.md
index 2a07e9b..697a506 100644
--- a/README.md
+++ b/README.md
@@ -8,34 +8,6 @@ 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
Get the packages you need and install a git hook to run tests before push:
From 0a9e71e8f0c0503585a80b543ea64fe9edf47902 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?c0ff3m4kr=20=E3=8B=9B?=
Date: Tue, 4 Nov 2014 11:01:27 +0100
Subject: [PATCH 12/54] Wildcard for HANDLEBARS_FILES
Using wildcard command to get all the .handlebar files.
TEMPLATES_JS will be generated again when the HANDLEBARS_FILES are newer.
---
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 9c9ac44..5ce77e0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
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
.PHONY: all
all: $(TEMPLATES_JS)
From daabc5536f54ad5034ab15644d25b17c4589c875 Mon Sep 17 00:00:00 2001
From: c0ff3m4kr
Date: Wed, 5 Nov 2014 15:05:50 +0100
Subject: [PATCH 13/54] Catch exceptions
---
routerapi/check_updates | 3 +++
1 file changed, 3 insertions(+)
diff --git a/routerapi/check_updates b/routerapi/check_updates
index 44eba55..eb73f64 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:
+ # catch exception and return error message
+ pass
finally:
nullfile.close()
From 70313087b35ffb9bd96d71cdcad818c7a2c8554e Mon Sep 17 00:00:00 2001
From: c0ff3m4kr
Date: Thu, 6 Nov 2014 12:10:20 +0100
Subject: [PATCH 14/54] only catch OSError Also using the same code for
update.py
---
routerapi/check_updates | 4 ++--
routerapi/update | 3 +++
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/routerapi/check_updates b/routerapi/check_updates
index eb73f64..ab8bd56 100755
--- a/routerapi/check_updates
+++ b/routerapi/check_updates
@@ -14,8 +14,8 @@ try:
ret = "not-up-to-date"
else:
ret = "up-to-date"
-except:
- # catch exception and return error message
+except OSError:
+ # catch call-errors and return error message
pass
finally:
nullfile.close()
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()
From c592d159653ddf9ada287233ab9da3985eec82b3 Mon Sep 17 00:00:00 2001
From: c0ff3m4kr
Date: Thu, 6 Nov 2014 14:45:53 +0100
Subject: [PATCH 15/54] Code style improvement Packed main code into methods
Moved globals to attribute functions Added exception which is raised instead
of calling from inside the class. Added some docstrings. Replaced has_key
with .
---
lib/update/update.py | 163 +++++++++++++++++++++++++++----------------
1 file changed, 104 insertions(+), 59 deletions(-)
diff --git a/lib/update/update.py b/lib/update/update.py
index d3244f6..9457f09 100755
--- a/lib/update/update.py
+++ b/lib/update/update.py
@@ -4,40 +4,54 @@
import systemwide_lock
import time
-openwrt_release_file = "/etc/openwrt_release"
-keyring = "/etc/update_key.gpg"
-update_url = "https://s.eff.org/files/openwireless/update.json.asc"
-sysupgrade_command = ["/usr/bin/sudo", "sysupgrade", "-v", "-n"]
-update_check_file = "/etc/last_update_check"
def failed(why):
sys.stderr.write("Failed %s\n" % why)
systemwide_lock.release_lock()
sys.exit(1)
+class UpdateError(Exception):
+ '''Exception raised if an error occures while updating.
+ '''
+ def __init__(self, message):
+ self.message = message
+
+ def __str__(self):
+ return ("Failed " + self.message)
+
class Updater(object):
+
+ openwrt_release_file = "/etc/openwrt_release"
+ keyring = "/etc/update_key.gpg"
+ update_url = "https://s.eff.org/files/openwireless/update.json.asc"
+ sysupgrade_command = ["/usr/bin/sudo", "sysupgrade", "-v", "-n"]
+ update_check_file = "/etc/last_update_check"
+
def __init__(self):
self.firmware = None
self.current = None
- with open(openwrt_release_file) as f:
+ with open(self.openwrt_release_file) as f:
for line in f:
m = re.match(r'^DISTRIB_RELEASE_DATE="(\d+)"$', line)
if m and len(m.groups()) == 1:
self.current = int(m.groups()[0])
break
- else:
- failed("to find current version in /etc/openwrt_release")
+ if self.current is None:
+ raise UpdateError("to find current version in " + self.openwrt_release_file)
self.purported_manifest = None
self.manifest = None
def get_manifest(self):
+ '''Download the manifest from eff.org.
+ Returns True on success and False if the download failed.
+ '''
buffer = StringIO.StringIO()
curl = pycurl.Curl()
curl.setopt(pycurl.PROXYPORT, 9050)
curl.setopt(pycurl.PROXY, "localhost")
curl.setopt(pycurl.PROXYTYPE, 6) # == PROXYTYPE_SOCKS4A
curl.setopt(pycurl.CAINFO, "/etc/ssl/certs/StartCom_Certification_Authority.crt")
- curl.setopt(pycurl.URL, update_url)
+ curl.setopt(pycurl.URL, self.update_url)
curl.setopt(pycurl.WRITEFUNCTION, buffer.write)
try:
curl.perform()
@@ -53,7 +67,8 @@ def valid_sig(self):
if not self.purported_manifest:
return False
in_fd, out_fd = os.pipe()
- command = ["gpg", "--keyring", keyring, "--no-default-keyring", "--status-fd", str(out_fd), "--decrypt"]
+ command = ["gpg", "--keyring", self.keyring, "--no-default-keyring",
+ "--status-fd", str(out_fd), "--decrypt"]
p = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
proc_stdout, proc_stderr = p.communicate(self.purported_manifest)
if p.returncode != 0:
@@ -73,6 +88,9 @@ def valid_sig(self):
return True
def download_file(self):
+ '''Downloads the update image to a temporary file and saves its
+ location to the attribute `firmware`.
+ '''
if not self.manifest or not self.manifest.has_key("url"):
return None
url = self.manifest["url"]
@@ -92,7 +110,9 @@ def download_file(self):
return True
def valid_firmware(self):
- if not (self.manifest.has_key("sha256") and self.manifest.has_key("size") and self.manifest.has_key("timestamp")):
+ if not self.manifest:
+ return False
+ if not ("sha256" in self.manifest and "size" in self.manifest and "timestamp" in self.manifest):
return False
if not self.is_newer():
return False
@@ -116,28 +136,83 @@ def do_update(self):
# This is unlikely to actually return if successful, because the
# sysupgrade command itself will likely kill the upgrader process
# and also reboot the device.
- return not subprocess.call(sysupgrade_command + [self.firmware])
+ return not subprocess.call(self.sysupgrade_command + [self.firmware])
def extract_manifest(self, what):
try:
extracted_version = json.loads(what)
if not isinstance(extracted_version, dict):
- failed("to extract a JSON-structured update manifest")
+ raise UpdateError("to extract a JSON-structured update manifest")
else:
return extracted_version
except ValueError, e:
- failed("to extract a JSON-structured update manifest")
- failed("not reached")
+ raise UpdateError("to extract a JSON-structured update manifest")
+ raise UpdateError("not reached")
def parse_manifest(self):
if not self.purported_manifest:
- raise Exception, "cannot get manifest"
+ raise UpdateError("to get the manifest")
if self.valid_sig():
self.manifest = self.extract_manifest(self.signed_manifest)
return True
else:
return False
+ @staticmethod
+ def __update_check_file(newer):
+ """Store the current time (in Javascript format) in the file that
+ tracks when we last checked for updates.
+ """
+ msg = "Updating " + self.update_check_file + " to indicate "
+ if not newer:
+ flag = " N"
+ msg += "no installable"
+ else:
+ flag = " Y"
+ msg += "an"
+ msg += " update is available."
+ with open(self.update_check_file, "w") as checkfile:
+ checkfile.write(repr(time.time()*1000) + flag)
+ return True
+
+ def check_for_updates(self, advise_only=False):
+ """Checks for new software version. If advise_only is True it doesn't
+ call do_update() otherwise True is returned if a new firmware version
+ is available and False if it is the current.
+ """
+ if not self.purported_manifest:
+ print "Getting update metadata..."
+ if not u.get_manifest():
+ raise UpdateError("to download update metadata")
+ print u.purported_manifest
+
+ if not self.manifest:
+ print "Validating update signature..."
+ if not self.parse_manifest():
+ # Parsing includes signature validity checking
+ raise UpdateError("to validate signature of update metdata")
+
+ print "Checking whether to update..."
+ newer = self.is_newer()
+ self.__update_check_file(newer)
+ if advise_only:
+ # In this case, the update script is being run merely to check
+ # and inform the user whether an update is available, not to
+ # install it.
+ return newer
+
+ print "Downloading new firmware image..."
+ if not self.download_file():
+ raise UpdateError("to download firmware image")
+
+ print "Validating downloaded image..."
+ if not self.valid_firmware():
+ raise UpdateError("to validate downloaded firmware image")
+
+ print "Installing image..."
+ return self.do_update()
+
+
if __name__ == '__main__':
advise_only = False
if len(sys.argv) > 1 and sys.argv[1] == 'check':
@@ -147,52 +222,22 @@ def parse_manifest(self):
if not systemwide_lock.get_lock():
failed("to acquire update lock")
u = Updater()
- print "Getting update metadata..."
- if not u.get_manifest():
- failed("to download update metadata")
- print u.purported_manifest
- print "Validating update signature..."
- if not u.parse_manifest(): # includes signature validity checking
- failed("to validate signature of update metdata")
-
- print "Checking whether to update..."
+ result = u.check_for_updates(advise_only)
if advise_only:
- # In this case, the update script is being run merely to check
- # and inform the user whether an update is available, not to
- # install it.
- # Store the current time (in Javascript format) in the
- # file that tracks when we last checked for updates.
- if u.is_newer():
- print "Updating " + update_check_file + " to indicate update is available."
- with open(update_check_file, "w") as f:
- f.write(repr(time.time()*1000) + " Y")
- systemwide_lock.release_lock()
+ # Release lock is called in the finally block
+ if result:
+ # update is available
sys.exit(0)
- else:
- print "Updating " + update_check_file + " to indicate no installable update available."
- with open(update_check_file, "w") as f:
- f.write(repr(time.time()*1000) + " N")
- systemwide_lock.release_lock()
- sys.exit(1)
- if u.is_newer():
- print "Updating " + update_check_file + " to indicate update is available."
- with open(update_check_file, "w") as f:
- f.write(repr(time.time()*1000) + " Y")
- print "Downloading new firmware image..."
- if not u.download_file():
- failed("to download firmware image")
- print "Validating downloaded image..."
- if u.valid_firmware():
- print "Installing image..."
- if not u.do_update():
- failed("to install update")
- subprocess.call(["/usr/bin/sudo", "/sbin/reboot"])
- else:
- failed("to validate downloaded firmware image")
+ # current version
+ sys.exit(1)
else:
- print "Updating " + update_check_file + " to indicate no installable update available."
- with open(update_check_file, "w") as f:
- f.write(repr(time.time()*1000) + " N")
+ if not result:
+ failed("to install update")
+ # Reboot if the installation completed but we're still alive
+ subprocess.call(["/usr/bin/sudo", "/sbin/reboot"])
+ except UpdateError as why:
+ # Catch "trusted" exception
+ failed(why.message)
except Exception, e:
print e
failed("to update for an undetermined reason.")
From c9e16ed3d615d8bc0afd3f91818669799f51526a Mon Sep 17 00:00:00 2001
From: c0ff3m4kr
Date: Thu, 6 Nov 2014 14:50:00 +0100
Subject: [PATCH 16/54] fixes typo
---
lib/update/update.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/update/update.py b/lib/update/update.py
index 9457f09..1532fbc 100755
--- a/lib/update/update.py
+++ b/lib/update/update.py
@@ -182,9 +182,9 @@ def check_for_updates(self, advise_only=False):
"""
if not self.purported_manifest:
print "Getting update metadata..."
- if not u.get_manifest():
+ if not self.get_manifest():
raise UpdateError("to download update metadata")
- print u.purported_manifest
+ print self.purported_manifest
if not self.manifest:
print "Validating update signature..."
From e211f65872fb13b44e149b9983251db3edd020ad Mon Sep 17 00:00:00 2001
From: c0ff3m4kr
Date: Thu, 6 Nov 2014 14:59:02 +0100
Subject: [PATCH 17/54] certificate as attribute
---
lib/update/update.py | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/lib/update/update.py b/lib/update/update.py
index 1532fbc..29088ce 100755
--- a/lib/update/update.py
+++ b/lib/update/update.py
@@ -26,7 +26,8 @@ class Updater(object):
update_url = "https://s.eff.org/files/openwireless/update.json.asc"
sysupgrade_command = ["/usr/bin/sudo", "sysupgrade", "-v", "-n"]
update_check_file = "/etc/last_update_check"
-
+ ca_file = "/etc/ssl/certs/StartCom_Certification_Authority.crt"
+
def __init__(self):
self.firmware = None
self.current = None
@@ -50,7 +51,7 @@ def get_manifest(self):
curl.setopt(pycurl.PROXYPORT, 9050)
curl.setopt(pycurl.PROXY, "localhost")
curl.setopt(pycurl.PROXYTYPE, 6) # == PROXYTYPE_SOCKS4A
- curl.setopt(pycurl.CAINFO, "/etc/ssl/certs/StartCom_Certification_Authority.crt")
+ curl.setopt(pycurl.CAINFO, self.ca_file)
curl.setopt(pycurl.URL, self.update_url)
curl.setopt(pycurl.WRITEFUNCTION, buffer.write)
try:
@@ -99,7 +100,7 @@ def download_file(self):
curl = pycurl.Curl()
curl.setopt(pycurl.URL, self.manifest["url"].encode("ascii"))
curl.setopt(pycurl.WRITEFUNCTION, buffer.write)
- curl.setopt(pycurl.CAINFO, "/etc/ssl/certs/StartCom_Certification_Authority.crt")
+ curl.setopt(pycurl.CAINFO, self.ca_file)
try:
curl.perform()
except Exception, e:
From 6e0b218b3965b680d6cb3721ae6b4a50be4c0ddc Mon Sep 17 00:00:00 2001
From: coff3m4kr
Date: Tue, 18 Nov 2014 19:29:09 +0100
Subject: [PATCH 18/54] Require a password which is at least 8 characters long
---
routerapi/auth.py | 6 ++++++
routerapi/change_password | 3 ++-
routerapi/change_password_first_time | 3 ++-
3 files changed, 10 insertions(+), 2 deletions(-)
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"
From 03058ff34457720fb97ed8d5a100a1c96fd0ab3b Mon Sep 17 00:00:00 2001
From: coff3m4kr
Date: Tue, 18 Nov 2014 19:43:56 +0100
Subject: [PATCH 19/54] check private wlan password length
---
routerapi/set_private_ssid | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
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)
From 4dab0a13cd55ace8261fa8f83ef602a4a822dafb Mon Sep 17 00:00:00 2001
From: Andrew Kiellor
Date: Tue, 18 Nov 2014 10:58:22 -0800
Subject: [PATCH 20/54] Added basic vagrant file with more dependencies
required for building.
* Using vagrant greatly reduces the barrier to contribution as it allows
folks with different operating systems to get up and running quickly.
* Creates a known development environment which can be centrally
maintained.
* Reduce the getting started documentation.
---
.gitignore | 1 +
Vagrantfile | 27 +++++++++++++++++++++++++++
install-dev-dependencies.sh | 2 +-
3 files changed, 29 insertions(+), 1 deletion(-)
create mode 100644 Vagrantfile
diff --git a/.gitignore b/.gitignore
index 2ab3a11..5783c09 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@
/env/
local-lighttpd/etc
local-lighttpd/port-*-etc
+.vagrant
diff --git a/Vagrantfile b/Vagrantfile
new file mode 100644
index 0000000..a61e591
--- /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: <
Date: Fri, 21 Nov 2014 15:15:25 -0800
Subject: [PATCH 21/54] Only link pre-push hook if it does not already exist.
* This is required to allow install-dev-dependencies.sh idempotent
(able to be run multiple times).
---
install-dev-dependencies.sh | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/install-dev-dependencies.sh b/install-dev-dependencies.sh
index 560ed6d..5473b95 100755
--- a/install-dev-dependencies.sh
+++ b/install-dev-dependencies.sh
@@ -6,6 +6,8 @@ cd $(dirname $0)
pip install --user -qr requirements.txt
npm install
# Install a hook to run tests before pushing.
-ln -s ../../run-tests.sh .git/hooks/pre-push
+if [ ! -f .git/hooks/pre-push ]; then
+ ln -s ../../run-tests.sh .git/hooks/pre-push
+fi
echo "We strongly recommend adding the lines from ./ssh-config to your" \
"SSH config. It will make developing on a router much faster."
From 298e7846e3ff4ecf2770933875bf43fb7477f42a Mon Sep 17 00:00:00 2001
From: Andrew Kiellor
Date: Sat, 22 Nov 2014 02:04:01 -0800
Subject: [PATCH 22/54] Add tftp to install-dev-dependencies.
* tftp is required in dev for flashing the wndr3800
---
install-dev-dependencies.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/install-dev-dependencies.sh b/install-dev-dependencies.sh
index 5473b95..352f9ca 100755
--- a/install-dev-dependencies.sh
+++ b/install-dev-dependencies.sh
@@ -1,7 +1,7 @@
#!/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 -y gettext unzip libncurses-dev subversion git inotify-tools lighttpd nodejs npm python2.7 python-pip
+sudo apt-get install -y gettext unzip libncurses-dev subversion git inotify-tools lighttpd nodejs npm python2.7 python-pip tftp
cd $(dirname $0)
pip install --user -qr requirements.txt
npm install
From 588997176828833cc8d262376e9bd0b49bff198e Mon Sep 17 00:00:00 2001
From: Andrew Kiellor
Date: Sat, 22 Nov 2014 02:07:24 -0800
Subject: [PATCH 23/54] Build image w/ image builder.
* Aim of this commit is to reduce build time in development. With this
building firmware from clean is about 8min in virtual machine, rather
than about 3hrs.
* Downloads and caches ImageBuilder from cerowrt/bufferbloat repository.
* Larger than a regular release.
* Currently has vanilla python rather than python-mini-eff. Building
python-mini-eff as a binary and hosting would resolve this issue.
* Caches all downloaded packages in .cache
---
.gitignore | 4 ++-
infra/repositories.conf | 11 +++++++
scripts/build-with-image-builder | 50 ++++++++++++++++++++++++++++++++
3 files changed, 64 insertions(+), 1 deletion(-)
create mode 100644 infra/repositories.conf
create mode 100755 scripts/build-with-image-builder
diff --git a/.gitignore b/.gitignore
index 5783c09..93cd2d3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,4 +8,6 @@
/env/
local-lighttpd/etc
local-lighttpd/port-*-etc
-.vagrant
+/.vagrant
+/.cache
+/dist
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/scripts/build-with-image-builder b/scripts/build-with-image-builder
new file mode 100755
index 0000000..f8e0e7a
--- /dev/null
+++ b/scripts/build-with-image-builder
@@ -0,0 +1,50 @@
+#!/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/
+
+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
From c61dcf8a743a711d67bed8a8f7559e15277f98a0 Mon Sep 17 00:00:00 2001
From: Andrew Kiellor
Date: Sat, 22 Nov 2014 11:59:35 -0800
Subject: [PATCH 24/54] Add libfontconfig to install-development-dependencies
(required for phantomjs)
---
install-dev-dependencies.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/install-dev-dependencies.sh b/install-dev-dependencies.sh
index 352f9ca..2ce0fac 100755
--- a/install-dev-dependencies.sh
+++ b/install-dev-dependencies.sh
@@ -1,7 +1,7 @@
#!/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 -y gettext unzip libncurses-dev subversion git inotify-tools lighttpd nodejs npm python2.7 python-pip tftp
+sudo apt-get install -y gettext unzip libncurses-dev subversion git inotify-tools lighttpd nodejs npm python2.7 python-pip tftp libfontconfig
cd $(dirname $0)
pip install --user -qr requirements.txt
npm install
From 43d7ffa891039b9e4d93a8beb33246f0f37eb407 Mon Sep 17 00:00:00 2001
From: Andrew Kiellor
Date: Sat, 22 Nov 2014 11:59:56 -0800
Subject: [PATCH 25/54] Link legacy node binary to new binary.
---
install-dev-dependencies.sh | 3 +++
1 file changed, 3 insertions(+)
diff --git a/install-dev-dependencies.sh b/install-dev-dependencies.sh
index 2ce0fac..cc58fa0 100755
--- a/install-dev-dependencies.sh
+++ b/install-dev-dependencies.sh
@@ -2,6 +2,9 @@
# On Ubuntu and similar systems, install packages that are necessary and/or
# useful to build and debug OpenWireless.
sudo apt-get install -y gettext unzip libncurses-dev subversion git inotify-tools lighttpd nodejs npm python2.7 python-pip tftp libfontconfig
+if [ ! -f /usr/bin/node ]; then
+ sudo ln -s /usr/bin/nodejs /usr/bin/node
+fi
cd $(dirname $0)
pip install --user -qr requirements.txt
npm install
From 6e711fb8649b3c08727557f3dfadbe967c33a4bd Mon Sep 17 00:00:00 2001
From: Andrew Kiellor
Date: Sun, 23 Nov 2014 01:22:50 -0800
Subject: [PATCH 26/54] Add firefox/xvfb for running functional tests in
virtual machine.
* Also had to upgrade selenium version to support newer version of
firefox.
* Xvfb is a virtual framebuffer which allows running GUI applications
without a real X windows environment.
---
infra/etc/init.d/Xvfb | 34 ++++++++++++++++++++++++++++++++++
install-dev-dependencies.sh | 4 +++-
requirements.txt | 2 +-
3 files changed, 38 insertions(+), 2 deletions(-)
create mode 100755 infra/etc/init.d/Xvfb
diff --git a/infra/etc/init.d/Xvfb b/infra/etc/init.d/Xvfb
new file mode 100755
index 0000000..60d09fe
--- /dev/null
+++ b/infra/etc/init.d/Xvfb
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+### BEGIN INIT INFO
+# Provides: Xvfb
+# Required-Start: $local_fs $remote_fs
+# Required-Stop:
+# X-Start-Before:
+# Default-Start: 2 3 4 5
+# Default-Stop:
+### END INIT INFO
+
+NAME=Xvfb
+INIT=/etc/init.d/$NAME
+PROGRAM=/usr/bin/$NAME
+PIDFILE=/var/run/$NAME.pid
+DISPLAY=:0
+
+set -e
+
+case "$1" in
+ start)
+start-stop-daemon --oknodo --background --make-pidfile --start --exec $PROGRAM --pidfile $PIDFILE -- $DIPLAY -screen 0 1024x768x24
+;;
+ stop)
+start-stop-daemon --oknodo --stop --pidfile $PIDFILE
+rm $PIDFILE
+;;
+ *)
+echo "Usage: $INIT {start|stop}" >&2
+exit 1
+;;
+esac
+
+exit 0
diff --git a/install-dev-dependencies.sh b/install-dev-dependencies.sh
index cc58fa0..d375bfb 100755
--- a/install-dev-dependencies.sh
+++ b/install-dev-dependencies.sh
@@ -1,7 +1,7 @@
#!/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 -y gettext unzip libncurses-dev subversion git inotify-tools lighttpd nodejs npm python2.7 python-pip tftp libfontconfig
+sudo apt-get install -y gettext unzip libncurses-dev subversion git inotify-tools lighttpd nodejs npm python2.7 python-pip tftp libfontconfig firefox xvfb
if [ ! -f /usr/bin/node ]; then
sudo ln -s /usr/bin/nodejs /usr/bin/node
fi
@@ -12,5 +12,7 @@ npm install
if [ ! -f .git/hooks/pre-push ]; then
ln -s ../../run-tests.sh .git/hooks/pre-push
fi
+sudo cp infra/etc/init.d/Xvfb /etc/init.d/Xvfb
+sudo service Xvfb start
echo "We strongly recommend adding the lines from ./ssh-config to your" \
"SSH config. It will make developing on a router much faster."
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
From 8d1d496cd908394ddf87eb95726bb7c62383af2d Mon Sep 17 00:00:00 2001
From: Andrew Kiellor
Date: Sun, 23 Nov 2014 02:34:47 -0800
Subject: [PATCH 27/54] Refactor pre-push script to use wrapper 'pre-commit'
* pre-commit should aim to do everything to validate
developer changes, this may extend beyond just 'run-tests.sh'
which runs unit tests.
* pre-commit is vagrant aware, so will run the command on
the vagrant box if vagrant is detected.
* if already on the vagrant box, will run tests locally.
---
install-dev-dependencies.sh | 2 +-
scripts/pre-commit | 13 +++++++++++++
2 files changed, 14 insertions(+), 1 deletion(-)
create mode 100755 scripts/pre-commit
diff --git a/install-dev-dependencies.sh b/install-dev-dependencies.sh
index d375bfb..124a336 100755
--- a/install-dev-dependencies.sh
+++ b/install-dev-dependencies.sh
@@ -10,7 +10,7 @@ pip install --user -qr requirements.txt
npm install
# Install a hook to run tests before pushing.
if [ ! -f .git/hooks/pre-push ]; then
- ln -s ../../run-tests.sh .git/hooks/pre-push
+ ln -s ../../scripts/pre-commit .git/hooks/pre-push
fi
sudo cp infra/etc/init.d/Xvfb /etc/init.d/Xvfb
sudo service Xvfb start
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
From 8f18b7f52b21432fbedfb2a2f0145a918a8b6ead Mon Sep 17 00:00:00 2001
From: Andrew Kiellor
Date: Sun, 23 Nov 2014 17:16:07 -0800
Subject: [PATCH 28/54] Fix DISPLAY setting in Xvfb init script.
---
infra/etc/init.d/Xvfb | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/infra/etc/init.d/Xvfb b/infra/etc/init.d/Xvfb
index 60d09fe..08613f2 100755
--- a/infra/etc/init.d/Xvfb
+++ b/infra/etc/init.d/Xvfb
@@ -9,17 +9,18 @@
# Default-Stop:
### END INIT INFO
+set -e
+set -o nounset
+
NAME=Xvfb
INIT=/etc/init.d/$NAME
PROGRAM=/usr/bin/$NAME
PIDFILE=/var/run/$NAME.pid
DISPLAY=:0
-set -e
-
case "$1" in
start)
-start-stop-daemon --oknodo --background --make-pidfile --start --exec $PROGRAM --pidfile $PIDFILE -- $DIPLAY -screen 0 1024x768x24
+start-stop-daemon --oknodo --background --make-pidfile --start --exec $PROGRAM --pidfile $PIDFILE -- $DISPLAY -screen 0 1024x768x24
;;
stop)
start-stop-daemon --oknodo --stop --pidfile $PIDFILE
From ec0e457806dd6cff4f0a67e8928b4883e06d2d87 Mon Sep 17 00:00:00 2001
From: c0ff3m4kr
Date: Mon, 24 Nov 2014 15:25:57 +0100
Subject: [PATCH 29/54] test case
---
test/auth_test.py | 2 ++
1 file changed, 2 insertions(+)
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")
From 6f70f64726b4b3b5edb470fbf8b7e26ef1285d28 Mon Sep 17 00:00:00 2001
From: c0ff3m4kr
Date: Mon, 24 Nov 2014 15:32:38 +0100
Subject: [PATCH 30/54] Revert "test case"
This reverts commit ec0e457806dd6cff4f0a67e8928b4883e06d2d87.
---
test/auth_test.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/test/auth_test.py b/test/auth_test.py
index e898305..6fd5dcc 100644
--- a/test/auth_test.py
+++ b/test/auth_test.py
@@ -58,8 +58,6 @@ 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")
From cb429cfda2bd265b2d2820cf48fbc0ca4528957a Mon Sep 17 00:00:00 2001
From: c0ff3m4kr
Date: Mon, 24 Nov 2014 15:37:36 +0100
Subject: [PATCH 31/54] Revert "certificate as attribute"
This reverts commit e211f65872fb13b44e149b9983251db3edd020ad.
---
lib/update/update.py | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/lib/update/update.py b/lib/update/update.py
index 29088ce..1532fbc 100755
--- a/lib/update/update.py
+++ b/lib/update/update.py
@@ -26,8 +26,7 @@ class Updater(object):
update_url = "https://s.eff.org/files/openwireless/update.json.asc"
sysupgrade_command = ["/usr/bin/sudo", "sysupgrade", "-v", "-n"]
update_check_file = "/etc/last_update_check"
- ca_file = "/etc/ssl/certs/StartCom_Certification_Authority.crt"
-
+
def __init__(self):
self.firmware = None
self.current = None
@@ -51,7 +50,7 @@ def get_manifest(self):
curl.setopt(pycurl.PROXYPORT, 9050)
curl.setopt(pycurl.PROXY, "localhost")
curl.setopt(pycurl.PROXYTYPE, 6) # == PROXYTYPE_SOCKS4A
- curl.setopt(pycurl.CAINFO, self.ca_file)
+ curl.setopt(pycurl.CAINFO, "/etc/ssl/certs/StartCom_Certification_Authority.crt")
curl.setopt(pycurl.URL, self.update_url)
curl.setopt(pycurl.WRITEFUNCTION, buffer.write)
try:
@@ -100,7 +99,7 @@ def download_file(self):
curl = pycurl.Curl()
curl.setopt(pycurl.URL, self.manifest["url"].encode("ascii"))
curl.setopt(pycurl.WRITEFUNCTION, buffer.write)
- curl.setopt(pycurl.CAINFO, self.ca_file)
+ curl.setopt(pycurl.CAINFO, "/etc/ssl/certs/StartCom_Certification_Authority.crt")
try:
curl.perform()
except Exception, e:
From c3f133dc7a6b56a4dfda8e62901ad57b917c7b26 Mon Sep 17 00:00:00 2001
From: c0ff3m4kr
Date: Mon, 24 Nov 2014 15:37:41 +0100
Subject: [PATCH 32/54] Revert "fixes typo"
This reverts commit c9e16ed3d615d8bc0afd3f91818669799f51526a.
---
lib/update/update.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/update/update.py b/lib/update/update.py
index 1532fbc..9457f09 100755
--- a/lib/update/update.py
+++ b/lib/update/update.py
@@ -182,9 +182,9 @@ def check_for_updates(self, advise_only=False):
"""
if not self.purported_manifest:
print "Getting update metadata..."
- if not self.get_manifest():
+ if not u.get_manifest():
raise UpdateError("to download update metadata")
- print self.purported_manifest
+ print u.purported_manifest
if not self.manifest:
print "Validating update signature..."
From 584b56df618e03bfe497fd8e2b842487c74ee5b3 Mon Sep 17 00:00:00 2001
From: c0ff3m4kr
Date: Mon, 24 Nov 2014 15:37:42 +0100
Subject: [PATCH 33/54] Revert "Code style improvement"
This reverts commit c592d159653ddf9ada287233ab9da3985eec82b3.
---
lib/update/update.py | 163 ++++++++++++++++---------------------------
1 file changed, 59 insertions(+), 104 deletions(-)
diff --git a/lib/update/update.py b/lib/update/update.py
index 9457f09..d3244f6 100755
--- a/lib/update/update.py
+++ b/lib/update/update.py
@@ -4,54 +4,40 @@
import systemwide_lock
import time
+openwrt_release_file = "/etc/openwrt_release"
+keyring = "/etc/update_key.gpg"
+update_url = "https://s.eff.org/files/openwireless/update.json.asc"
+sysupgrade_command = ["/usr/bin/sudo", "sysupgrade", "-v", "-n"]
+update_check_file = "/etc/last_update_check"
def failed(why):
sys.stderr.write("Failed %s\n" % why)
systemwide_lock.release_lock()
sys.exit(1)
-class UpdateError(Exception):
- '''Exception raised if an error occures while updating.
- '''
- def __init__(self, message):
- self.message = message
-
- def __str__(self):
- return ("Failed " + self.message)
-
class Updater(object):
-
- openwrt_release_file = "/etc/openwrt_release"
- keyring = "/etc/update_key.gpg"
- update_url = "https://s.eff.org/files/openwireless/update.json.asc"
- sysupgrade_command = ["/usr/bin/sudo", "sysupgrade", "-v", "-n"]
- update_check_file = "/etc/last_update_check"
-
def __init__(self):
self.firmware = None
self.current = None
- with open(self.openwrt_release_file) as f:
+ with open(openwrt_release_file) as f:
for line in f:
m = re.match(r'^DISTRIB_RELEASE_DATE="(\d+)"$', line)
if m and len(m.groups()) == 1:
self.current = int(m.groups()[0])
break
- if self.current is None:
- raise UpdateError("to find current version in " + self.openwrt_release_file)
+ else:
+ failed("to find current version in /etc/openwrt_release")
self.purported_manifest = None
self.manifest = None
def get_manifest(self):
- '''Download the manifest from eff.org.
- Returns True on success and False if the download failed.
- '''
buffer = StringIO.StringIO()
curl = pycurl.Curl()
curl.setopt(pycurl.PROXYPORT, 9050)
curl.setopt(pycurl.PROXY, "localhost")
curl.setopt(pycurl.PROXYTYPE, 6) # == PROXYTYPE_SOCKS4A
curl.setopt(pycurl.CAINFO, "/etc/ssl/certs/StartCom_Certification_Authority.crt")
- curl.setopt(pycurl.URL, self.update_url)
+ curl.setopt(pycurl.URL, update_url)
curl.setopt(pycurl.WRITEFUNCTION, buffer.write)
try:
curl.perform()
@@ -67,8 +53,7 @@ def valid_sig(self):
if not self.purported_manifest:
return False
in_fd, out_fd = os.pipe()
- command = ["gpg", "--keyring", self.keyring, "--no-default-keyring",
- "--status-fd", str(out_fd), "--decrypt"]
+ command = ["gpg", "--keyring", keyring, "--no-default-keyring", "--status-fd", str(out_fd), "--decrypt"]
p = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
proc_stdout, proc_stderr = p.communicate(self.purported_manifest)
if p.returncode != 0:
@@ -88,9 +73,6 @@ def valid_sig(self):
return True
def download_file(self):
- '''Downloads the update image to a temporary file and saves its
- location to the attribute `firmware`.
- '''
if not self.manifest or not self.manifest.has_key("url"):
return None
url = self.manifest["url"]
@@ -110,9 +92,7 @@ def download_file(self):
return True
def valid_firmware(self):
- if not self.manifest:
- return False
- if not ("sha256" in self.manifest and "size" in self.manifest and "timestamp" in self.manifest):
+ if not (self.manifest.has_key("sha256") and self.manifest.has_key("size") and self.manifest.has_key("timestamp")):
return False
if not self.is_newer():
return False
@@ -136,83 +116,28 @@ def do_update(self):
# This is unlikely to actually return if successful, because the
# sysupgrade command itself will likely kill the upgrader process
# and also reboot the device.
- return not subprocess.call(self.sysupgrade_command + [self.firmware])
+ return not subprocess.call(sysupgrade_command + [self.firmware])
def extract_manifest(self, what):
try:
extracted_version = json.loads(what)
if not isinstance(extracted_version, dict):
- raise UpdateError("to extract a JSON-structured update manifest")
+ failed("to extract a JSON-structured update manifest")
else:
return extracted_version
except ValueError, e:
- raise UpdateError("to extract a JSON-structured update manifest")
- raise UpdateError("not reached")
+ failed("to extract a JSON-structured update manifest")
+ failed("not reached")
def parse_manifest(self):
if not self.purported_manifest:
- raise UpdateError("to get the manifest")
+ raise Exception, "cannot get manifest"
if self.valid_sig():
self.manifest = self.extract_manifest(self.signed_manifest)
return True
else:
return False
- @staticmethod
- def __update_check_file(newer):
- """Store the current time (in Javascript format) in the file that
- tracks when we last checked for updates.
- """
- msg = "Updating " + self.update_check_file + " to indicate "
- if not newer:
- flag = " N"
- msg += "no installable"
- else:
- flag = " Y"
- msg += "an"
- msg += " update is available."
- with open(self.update_check_file, "w") as checkfile:
- checkfile.write(repr(time.time()*1000) + flag)
- return True
-
- def check_for_updates(self, advise_only=False):
- """Checks for new software version. If advise_only is True it doesn't
- call do_update() otherwise True is returned if a new firmware version
- is available and False if it is the current.
- """
- if not self.purported_manifest:
- print "Getting update metadata..."
- if not u.get_manifest():
- raise UpdateError("to download update metadata")
- print u.purported_manifest
-
- if not self.manifest:
- print "Validating update signature..."
- if not self.parse_manifest():
- # Parsing includes signature validity checking
- raise UpdateError("to validate signature of update metdata")
-
- print "Checking whether to update..."
- newer = self.is_newer()
- self.__update_check_file(newer)
- if advise_only:
- # In this case, the update script is being run merely to check
- # and inform the user whether an update is available, not to
- # install it.
- return newer
-
- print "Downloading new firmware image..."
- if not self.download_file():
- raise UpdateError("to download firmware image")
-
- print "Validating downloaded image..."
- if not self.valid_firmware():
- raise UpdateError("to validate downloaded firmware image")
-
- print "Installing image..."
- return self.do_update()
-
-
if __name__ == '__main__':
advise_only = False
if len(sys.argv) > 1 and sys.argv[1] == 'check':
@@ -222,22 +147,52 @@ def check_for_updates(self, advise_only=False):
if not systemwide_lock.get_lock():
failed("to acquire update lock")
u = Updater()
- result = u.check_for_updates(advise_only)
+ print "Getting update metadata..."
+ if not u.get_manifest():
+ failed("to download update metadata")
+ print u.purported_manifest
+ print "Validating update signature..."
+ if not u.parse_manifest(): # includes signature validity checking
+ failed("to validate signature of update metdata")
+
+ print "Checking whether to update..."
if advise_only:
- # Release lock is called in the finally block
- if result:
- # update is available
+ # In this case, the update script is being run merely to check
+ # and inform the user whether an update is available, not to
+ # install it.
+ # Store the current time (in Javascript format) in the
+ # file that tracks when we last checked for updates.
+ if u.is_newer():
+ print "Updating " + update_check_file + " to indicate update is available."
+ with open(update_check_file, "w") as f:
+ f.write(repr(time.time()*1000) + " Y")
+ systemwide_lock.release_lock()
sys.exit(0)
- # current version
- sys.exit(1)
+ else:
+ print "Updating " + update_check_file + " to indicate no installable update available."
+ with open(update_check_file, "w") as f:
+ f.write(repr(time.time()*1000) + " N")
+ systemwide_lock.release_lock()
+ sys.exit(1)
+ if u.is_newer():
+ print "Updating " + update_check_file + " to indicate update is available."
+ with open(update_check_file, "w") as f:
+ f.write(repr(time.time()*1000) + " Y")
+ print "Downloading new firmware image..."
+ if not u.download_file():
+ failed("to download firmware image")
+ print "Validating downloaded image..."
+ if u.valid_firmware():
+ print "Installing image..."
+ if not u.do_update():
+ failed("to install update")
+ subprocess.call(["/usr/bin/sudo", "/sbin/reboot"])
+ else:
+ failed("to validate downloaded firmware image")
else:
- if not result:
- failed("to install update")
- # Reboot if the installation completed but we're still alive
- subprocess.call(["/usr/bin/sudo", "/sbin/reboot"])
- except UpdateError as why:
- # Catch "trusted" exception
- failed(why.message)
+ print "Updating " + update_check_file + " to indicate no installable update available."
+ with open(update_check_file, "w") as f:
+ f.write(repr(time.time()*1000) + " N")
except Exception, e:
print e
failed("to update for an undetermined reason.")
From a362dd4bb5b5c0869a778628123fd8a67f09e3ae Mon Sep 17 00:00:00 2001
From: c0ff3m4kr
Date: Mon, 24 Nov 2014 15:37:43 +0100
Subject: [PATCH 34/54] Revert "Revert "test case""
This reverts commit 6f70f64726b4b3b5edb470fbf8b7e26ef1285d28.
---
test/auth_test.py | 2 ++
1 file changed, 2 insertions(+)
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")
From 2ed0dd98b53a59b57aa1b6a86ac04275bfac8f42 Mon Sep 17 00:00:00 2001
From: Andrew Kiellor
Date: Mon, 24 Nov 2014 16:55:44 -0800
Subject: [PATCH 35/54] Add options to install-dev-dependencies.sh for whether
to prompt and/or install Xvfb.
---
Vagrantfile | 2 +-
install-dev-dependencies.sh | 51 +++++++++++++++++++++++++++++++++----
2 files changed, 47 insertions(+), 6 deletions(-)
diff --git a/Vagrantfile b/Vagrantfile
index a61e591..a5ac0e2 100644
--- a/Vagrantfile
+++ b/Vagrantfile
@@ -15,7 +15,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.provision "shell", inline: <
Date: Mon, 24 Nov 2014 17:18:50 -0800
Subject: [PATCH 36/54] Switch xvfb to use upstart...starts on reboot!
---
infra/etc/init.d/Xvfb | 35 -----------------------------------
infra/etc/init/xvfb.conf | 12 ++++++++++++
install-dev-dependencies.sh | 4 ++--
3 files changed, 14 insertions(+), 37 deletions(-)
delete mode 100755 infra/etc/init.d/Xvfb
create mode 100644 infra/etc/init/xvfb.conf
diff --git a/infra/etc/init.d/Xvfb b/infra/etc/init.d/Xvfb
deleted file mode 100755
index 08613f2..0000000
--- a/infra/etc/init.d/Xvfb
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/sh
-
-### BEGIN INIT INFO
-# Provides: Xvfb
-# Required-Start: $local_fs $remote_fs
-# Required-Stop:
-# X-Start-Before:
-# Default-Start: 2 3 4 5
-# Default-Stop:
-### END INIT INFO
-
-set -e
-set -o nounset
-
-NAME=Xvfb
-INIT=/etc/init.d/$NAME
-PROGRAM=/usr/bin/$NAME
-PIDFILE=/var/run/$NAME.pid
-DISPLAY=:0
-
-case "$1" in
- start)
-start-stop-daemon --oknodo --background --make-pidfile --start --exec $PROGRAM --pidfile $PIDFILE -- $DISPLAY -screen 0 1024x768x24
-;;
- stop)
-start-stop-daemon --oknodo --stop --pidfile $PIDFILE
-rm $PIDFILE
-;;
- *)
-echo "Usage: $INIT {start|stop}" >&2
-exit 1
-;;
-esac
-
-exit 0
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/install-dev-dependencies.sh b/install-dev-dependencies.sh
index 1c2632b..5c79f8a 100755
--- a/install-dev-dependencies.sh
+++ b/install-dev-dependencies.sh
@@ -40,8 +40,8 @@ fi
if [ -n "$INSTALL_XVFB" ]; then
echo Okay, installing xvfb for you ':)'
sudo apt-get install $ACCEPT_INSTALL_PROMPTS xvfb
- sudo cp infra/etc/init.d/Xvfb /etc/init.d/Xvfb
- sudo service Xvfb start
+ sudo cp infra/etc/init/xvfb.conf /etc/init/xvfb.conf
+ sudo service xvfb start
fi
cat <
Date: Tue, 25 Nov 2014 00:42:36 -0800
Subject: [PATCH 37/54] Allow running the openwireless frontend w/ fake uci on
vagrant box.
OpenWireless requires the ability to modify permissions of files
on disk. The vagrant mount '/vagrant' does not allow permissions to
be modified, so this change mounts the running application in the
temp filesystem.
---
local-lighttpd/run-local-lighttpd.sh | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/local-lighttpd/run-local-lighttpd.sh b/local-lighttpd/run-local-lighttpd.sh
index 72ba1a5..7394d8b 100755
--- a/local-lighttpd/run-local-lighttpd.sh
+++ b/local-lighttpd/run-local-lighttpd.sh
@@ -3,10 +3,12 @@ DIR=$(dirname $0)
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
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",
From d5500000bebbd29b0bdfa396ca655553b759caf6 Mon Sep 17 00:00:00 2001
From: Andrew Kiellor
Date: Tue, 25 Nov 2014 00:54:03 -0800
Subject: [PATCH 38/54] Updated README.md to include Vagrant documentation.
---
README.md | 33 +++++++++++++++++++++++++++++++--
1 file changed, 31 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 697a506..6faee05 100644
--- a/README.md
+++ b/README.md
@@ -10,21 +10,50 @@ https://openwireless.org/.
# 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
From 52a987da0e266cf735c63b9c6967182476ea39d3 Mon Sep 17 00:00:00 2001
From: Sophie Krisch
Date: Tue, 25 Nov 2014 11:50:39 -0800
Subject: [PATCH 39/54] Fixed #220 [Sophie, Shane] Updating the
last-checked-date both when you are already up to date and when you
successfully download an update.
---
app/js/dashboard.js | 10 ++++++++--
app/js/update.js | 16 ++++++++++++++++
2 files changed, 24 insertions(+), 2 deletions(-)
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/update.js b/app/js/update.js
index d59974a..a1be05b 100644
--- a/app/js/update.js
+++ b/app/js/update.js
@@ -2,6 +2,7 @@ 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?")){
@@ -10,14 +11,29 @@ var updateModule = (function(){
}
};
+ 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": {}
};
From 044c1d07f3ba0f23a40cfb766d7ce7b57a63a5b6 Mon Sep 17 00:00:00 2001
From: Steven Lowe
Date: Tue, 25 Nov 2014 12:15:43 -0800
Subject: [PATCH 40/54] FIXED #211 - alignment issue with add ssh key controls
and software version.
---
app/css/admin-style.css | 7 ++++++-
app/js/templates.js | 2 +-
app/templates/settings.handlebars | 6 ++++--
3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/app/css/admin-style.css b/app/css/admin-style.css
index c5d0524..bcb61ca 100644
--- a/app/css/admin-style.css
+++ b/app/css/admin-style.css
@@ -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;
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/templates/settings.handlebars b/app/templates/settings.handlebars
index d8e91c4..704f58b 100644
--- a/app/templates/settings.handlebars
+++ b/app/templates/settings.handlebars
@@ -27,8 +27,10 @@
after which it will be locked to prevent tampering. Further
updates can be made via SSH login.
-
-
+