From 6a6c3e01529c94507f984cc1a77393aae8b4e266 Mon Sep 17 00:00:00 2001 From: lorenzoPrimi Date: Sun, 15 Jan 2017 15:16:26 +0100 Subject: [PATCH] Background mode (#56) --- .gitignore | 4 +- Podfile | 2 +- Podfile.lock | 8 +- ooniprobe.xcodeproj/project.pbxproj | 32 +- .../UserInterfaceState.xcuserstate | Bin 32742 -> 0 bytes ooniprobe/AppDelegate.h | 1 + ooniprobe/AppDelegate.mm | 7 + ooniprobe/Base.lproj/Localizable.strings | 11 + ooniprobe/Base.lproj/Main copia.storyboard | 818 ----------- ooniprobe/Base.lproj/Main.storyboard | 43 +- ooniprobe/DefaultPreferences.plist | 8 +- ooniprobe/Info.plist | 6 +- ooniprobe/Model/NetworkMeasurement.h | 2 + ooniprobe/Model/NetworkMeasurement.mm | 205 +-- ooniprobe/PrefixHeader.pch | 2 +- ooniprobe/Resources/fixtures/global.txt | 1218 +++++++++++++++++ ooniprobe/Resources/fixtures/urls.txt | 10 - .../IntroductionViewController.m | 1 + ooniprobe/View/SettingsTableViewController.h | 7 +- ooniprobe/View/SettingsTableViewController.m | 173 ++- ooniprobe/View/ViewController.mm | 14 +- 21 files changed, 1575 insertions(+), 997 deletions(-) delete mode 100644 ooniprobe.xcworkspace/xcuserdata/lorenzo.xcuserdatad/UserInterfaceState.xcuserstate delete mode 100644 ooniprobe/Base.lproj/Main copia.storyboard create mode 100644 ooniprobe/Resources/fixtures/global.txt delete mode 100644 ooniprobe/Resources/fixtures/urls.txt diff --git a/.gitignore b/.gitignore index b2b486871..ce3e5ea36 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ .DS_Store -NetProbe.xcodeproj/project.xcworkspace/xcuserdata/ -NetProbe.xcworkspace/xcuserdata/ +ooniprobe.xcodeproj/project.xcworkspace/xcuserdata/ +ooniprobe.xcworkspace/xcuserdata/ Podfile.lock Pods/ diff --git a/Podfile b/Podfile index 79ad0794f..f084fa112 100644 --- a/Podfile +++ b/Podfile @@ -3,7 +3,7 @@ target 'ooniprobe' do # pod 'measurement_kit', '~> 0.1.2.1' pod 'measurement_kit', :git => 'https://github.com/measurement-kit/measurement-kit.git', - :branch => 'release/v0.4.0-beta' + :branch => 'stable' pod 'Toast' pod 'sundown' end diff --git a/Podfile.lock b/Podfile.lock index bd2ca37fb..4e80bd223 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - measurement_kit (0.4.0-alpha) + - measurement_kit (0.4.0-beta) - sundown (0.1.0) - Toast (3.1.0) @@ -15,14 +15,14 @@ EXTERNAL SOURCES: CHECKOUT OPTIONS: measurement_kit: - :commit: 40cb030240bb20d1a686a770e818d5e818f3909d + :commit: f547d971b7a33f29cb77e0be6898b469d97d1928 :git: https://github.com/measurement-kit/measurement-kit.git SPEC CHECKSUMS: - measurement_kit: 02e47e4625e882c7a28ff6b7eae1c9752431e4c9 + measurement_kit: 1f8ac2368a6eae1018b9ded4ae8e8525ccea4438 sundown: 240edd458462fd773a474023559622c3a8566b5e Toast: 14a93686d6c8bfe2727afd342414e35660a8a1f3 PODFILE CHECKSUM: b1d8130a811b7b0a00f119d95a460f16367657b9 -COCOAPODS: 1.1.0.rc.2 +COCOAPODS: 1.1.1 diff --git a/ooniprobe.xcodeproj/project.pbxproj b/ooniprobe.xcodeproj/project.pbxproj index cc37e56d6..aad9cc425 100644 --- a/ooniprobe.xcodeproj/project.pbxproj +++ b/ooniprobe.xcodeproj/project.pbxproj @@ -32,11 +32,11 @@ ED3AB3321D2337920061F266 /* GeoIPASNum.dat in Resources */ = {isa = PBXBuildFile; fileRef = ED3AB32F1D2337920061F266 /* GeoIPASNum.dat */; }; ED4D60561A7162C400777275 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = ED4D60541A7162C400777275 /* Localizable.strings */; }; ED58E8CA1D0C627D00C74F10 /* TestStorage.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED58E8C91D0C627D00C74F10 /* TestStorage.mm */; }; + ED5AFD661E2529400039ECCB /* global.txt in Resources */ = {isa = PBXBuildFile; fileRef = ED5AFD651E2529400039ECCB /* global.txt */; }; ED8816AE1D8C6A3400D5D725 /* IntroductionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = ED8816AD1D8C6A3400D5D725 /* IntroductionViewController.m */; }; ED8816B41D8C6A4B00D5D725 /* RisksViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = ED8816B31D8C6A4B00D5D725 /* RisksViewController.m */; }; ED8816B71D8C6A5600D5D725 /* QuizViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = ED8816B61D8C6A5600D5D725 /* QuizViewController.m */; }; ED8816BA1D8C6A6100D5D725 /* ConfigurationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = ED8816B91D8C6A6100D5D725 /* ConfigurationViewController.m */; }; - ED9BBAAD1D847182005A3A57 /* urls.txt in Resources */ = {isa = PBXBuildFile; fileRef = ED9BBAAC1D847182005A3A57 /* urls.txt */; }; EDA193DA1C9AE36F00A49EAA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EDA193D81C9AE36F00A49EAA /* Main.storyboard */; }; EDA22FFE1DD61B6400BD8708 /* UIWebView+Markdown.m in Sources */ = {isa = PBXBuildFile; fileRef = EDA22FFD1DD61B6300BD8708 /* UIWebView+Markdown.m */; }; EDC73E5D1D9B266E00245184 /* ResultSelectorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EDC73E5C1D9B266E00245184 /* ResultSelectorViewController.m */; }; @@ -105,6 +105,7 @@ ED4D60551A7162C400777275 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; ED58E8C81D0C627D00C74F10 /* TestStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestStorage.h; path = Utility/TestStorage.h; sourceTree = ""; }; ED58E8C91D0C627D00C74F10 /* TestStorage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = TestStorage.mm; path = Utility/TestStorage.mm; sourceTree = ""; }; + ED5AFD651E2529400039ECCB /* global.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = global.txt; sourceTree = ""; }; ED8816AC1D8C6A3400D5D725 /* IntroductionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IntroductionViewController.h; path = "Informed consent/IntroductionViewController.h"; sourceTree = ""; }; ED8816AD1D8C6A3400D5D725 /* IntroductionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IntroductionViewController.m; path = "Informed consent/IntroductionViewController.m"; sourceTree = ""; }; ED8816B21D8C6A4B00D5D725 /* RisksViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RisksViewController.h; path = "Informed consent/RisksViewController.h"; sourceTree = ""; }; @@ -113,7 +114,6 @@ ED8816B61D8C6A5600D5D725 /* QuizViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = QuizViewController.m; path = "Informed consent/QuizViewController.m"; sourceTree = ""; }; ED8816B81D8C6A6100D5D725 /* ConfigurationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConfigurationViewController.h; path = "Informed consent/ConfigurationViewController.h"; sourceTree = ""; }; ED8816B91D8C6A6100D5D725 /* ConfigurationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ConfigurationViewController.m; path = "Informed consent/ConfigurationViewController.m"; sourceTree = ""; }; - ED9BBAAC1D847182005A3A57 /* urls.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = urls.txt; sourceTree = ""; }; EDA193D91C9AE36F00A49EAA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; EDA22FFB1DD5D39000BD8708 /* PrefixHeader.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrefixHeader.pch; sourceTree = ""; }; EDA22FFC1DD61B6300BD8708 /* UIWebView+Markdown.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIWebView+Markdown.h"; path = "Utility/UIWebView+Markdown.h"; sourceTree = ""; }; @@ -249,7 +249,7 @@ D4A2F62E1A6C33F7001B8460 /* fixtures */ = { isa = PBXGroup; children = ( - ED9BBAAC1D847182005A3A57 /* urls.txt */, + ED5AFD651E2529400039ECCB /* global.txt */, D4A2F62F1A6C33F7001B8460 /* hosts.txt */, ); path = fixtures; @@ -399,7 +399,13 @@ TargetAttributes = { D4A2F5D81A6C3244001B8460 = { CreatedOnToolsVersion = 6.1.1; - DevelopmentTeam = YUY24YXWK4; + DevelopmentTeam = 5YRT8MW288; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.BackgroundModes = { + enabled = 1; + }; + }; }; }; }; @@ -430,7 +436,6 @@ ED3AB3311D2337920061F266 /* GeoIP.dat in Resources */, EDE32B5E1D5CCABB00D7B4CF /* 1dc35d25e61d819a9c357074014867ab.ttf in Resources */, EDE32B6B1D5CCABB00D7B4CF /* c8ddf1e5e5bf3682bc7bebf30f394148.woff in Resources */, - ED9BBAAD1D847182005A3A57 /* urls.txt in Resources */, ED3AB3301D2337920061F266 /* cacert.pem in Resources */, EDE32B731D5CCABB00D7B4CF /* index.html in Resources */, EDCB9D911CB3F9ED00BBA3BC /* DefaultPreferences.plist in Resources */, @@ -445,6 +450,7 @@ ED09BE331D07083A00757F4D /* tcp-connect.html in Resources */, EDE32B611D5CCABB00D7B4CF /* 448c34a56d699c29117adc64c43affeb.woff2 in Resources */, EDE32B6D1D5CCABB00D7B4CF /* d7c639084f684d66a1bc66855d193ed8.svg in Resources */, + ED5AFD661E2529400039ECCB /* global.txt in Resources */, D4A2F5ED1A6C3244001B8460 /* LaunchScreen.xib in Resources */, EDA193DA1C9AE36F00A49EAA /* Main.storyboard in Resources */, EDEDE80C1DD1EB01002C732A /* setup-mobile.css in Resources */, @@ -676,8 +682,8 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; CODE_SIGN_IDENTITY = "iPhone Developer: Lorenzo Primiterra (XUC4X5K526)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Lorenzo Primiterra (XUC4X5K526)"; - DEVELOPMENT_TEAM = YUY24YXWK4; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEVELOPMENT_TEAM = 5YRT8MW288; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_INLINES_ARE_PRIVATE_EXTERN = NO; @@ -694,8 +700,8 @@ LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = org.openobservatory.NetProbe; PRODUCT_NAME = ooniprobe; - PROVISIONING_PROFILE = "c5d9cb6f-de80-490e-8130-cc0d4e7da888"; - PROVISIONING_PROFILE_SPECIFIER = "ooniprobe-dev"; + PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; TARGETED_DEVICE_FAMILY = "1,2"; USER_HEADER_SEARCH_PATHS = ""; }; @@ -709,8 +715,8 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; CODE_SIGN_IDENTITY = "iPhone Distribution: Lorenzo Primiterra (YUY24YXWK4)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Lorenzo Primiterra (YUY24YXWK4)"; - DEVELOPMENT_TEAM = YUY24YXWK4; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEVELOPMENT_TEAM = 5YRT8MW288; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_INLINES_ARE_PRIVATE_EXTERN = NO; @@ -727,8 +733,8 @@ LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = org.openobservatory.NetProbe; PRODUCT_NAME = ooniprobe; - PROVISIONING_PROFILE = "f5941269-8ba7-4c3f-b553-1e7483e96894"; - PROVISIONING_PROFILE_SPECIFIER = "NetProbe-distr"; + PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; TARGETED_DEVICE_FAMILY = "1,2"; USER_HEADER_SEARCH_PATHS = ""; }; diff --git a/ooniprobe.xcworkspace/xcuserdata/lorenzo.xcuserdatad/UserInterfaceState.xcuserstate b/ooniprobe.xcworkspace/xcuserdata/lorenzo.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index 1bf8867c7a93ab54ca3af5408987b799f51f2d91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32742 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 JM^Vj5{~w7ZKI8xZ diff --git a/ooniprobe/AppDelegate.h b/ooniprobe/AppDelegate.h index 37c7fa109..3518da1a2 100644 --- a/ooniprobe/AppDelegate.h +++ b/ooniprobe/AppDelegate.h @@ -8,6 +8,7 @@ @property (strong, nonatomic) UIWindow *window; +- (void)registerNotifications; @end diff --git a/ooniprobe/AppDelegate.mm b/ooniprobe/AppDelegate.mm index 5b562c9d1..9b757f76e 100644 --- a/ooniprobe/AppDelegate.mm +++ b/ooniprobe/AppDelegate.mm @@ -16,9 +16,15 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( [[UINavigationBar appearance] setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys: [UIColor whiteColor], NSForegroundColorAttributeName, [UIFont fontWithName:@"HelveticaNeue" size:20], NSFontAttributeName, nil]]; [[UIBarButtonItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys: [UIFont fontWithName:@"HelveticaNeue" size:16],NSFontAttributeName, nil] forState:UIControlStateNormal]; [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; + [self registerNotifications]; return YES; } +- (void)registerNotifications{ + if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]){ + [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]]; + } +} - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. @@ -35,6 +41,7 @@ - (void)applicationWillEnterForeground:(UIApplication *)application { - (void)applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + [UIApplication sharedApplication].applicationIconBadgeNumber = 0; } - (void)applicationWillTerminate:(UIApplication *)application { diff --git a/ooniprobe/Base.lproj/Localizable.strings b/ooniprobe/Base.lproj/Localizable.strings index 3961901f5..38231f24b 100644 --- a/ooniprobe/Base.lproj/Localizable.strings +++ b/ooniprobe/Base.lproj/Localizable.strings @@ -80,3 +80,14 @@ "no_result" = "No results"; "no_result_msg" = "The test has no results or it was aborted"; + +"local_notifications" = "Run test reminder"; +"local_notifications_time" = "Time"; +"local_notifications_text" = "Time to run tests"; + +"collector_settings" = "Collector settings"; +"notifications" = "Notifications"; + +"max_runtime" = "Max runtime (seconds)"; +"test_limits" = "Test limits"; +"finished_running" = "%@ finished running"; diff --git a/ooniprobe/Base.lproj/Main copia.storyboard b/ooniprobe/Base.lproj/Main copia.storyboard deleted file mode 100644 index 4828b0bc4..000000000 --- a/ooniprobe/Base.lproj/Main copia.storyboard +++ /dev/null @@ -1,818 +0,0 @@ - - - - - - - - - - - - - - Inconsolata - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This setup wizard will help you get started with ooniprobe. It should take about 5 minutes. - -The Open Observatory of Network Interference (OONI) works to fight network censorship and surveillance. - -By running this software, you may be putting yourself at risk. - -The next two steps of this wizard will walk you through some of the potential dangers. Please bear with us, as this is important! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ooniprobe/Base.lproj/Main.storyboard b/ooniprobe/Base.lproj/Main.storyboard index 51ff22c87..6c9c69eb3 100644 --- a/ooniprobe/Base.lproj/Main.storyboard +++ b/ooniprobe/Base.lproj/Main.storyboard @@ -1,11 +1,11 @@ - + - + @@ -15,7 +15,7 @@ - + @@ -367,6 +367,43 @@ The next two steps of this wizard will walk you through some of the potential da + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ooniprobe/DefaultPreferences.plist b/ooniprobe/DefaultPreferences.plist index 9ce0ed8eb..1e813e965 100644 --- a/ooniprobe/DefaultPreferences.plist +++ b/ooniprobe/DefaultPreferences.plist @@ -2,6 +2,8 @@ + local_notifications + include_ip include_asn @@ -10,7 +12,11 @@ YES upload_results YES + local_notifications_time + 2017-01-01T17:00:00Z + max_runtime + 90 collector_address - https://measurement-kit-collector.herokuapp.com + https://b.collector.ooni.io diff --git a/ooniprobe/Info.plist b/ooniprobe/Info.plist index 7e3796510..a0249a81b 100644 --- a/ooniprobe/Info.plist +++ b/ooniprobe/Info.plist @@ -19,7 +19,7 @@ CFBundleSignature ???? CFBundleVersion - 15 + 17 Fabric APIKey @@ -43,6 +43,10 @@ NSAllowsArbitraryLoads + UIBackgroundModes + + fetch + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile diff --git a/ooniprobe/Model/NetworkMeasurement.h b/ooniprobe/Model/NetworkMeasurement.h index 0d9620bc9..d253ecb7b 100644 --- a/ooniprobe/Model/NetworkMeasurement.h +++ b/ooniprobe/Model/NetworkMeasurement.h @@ -20,6 +20,7 @@ bool include_cc; bool upload_results; NSString *collector_address; + NSNumber *max_runtime; } @property NSString *name; @@ -31,6 +32,7 @@ @property NSString *log_file; @property BOOL completed; @property mk::Settings options; +@property (nonatomic) UIBackgroundTaskIdentifier backgroundTask; -(void) run; @end diff --git a/ooniprobe/Model/NetworkMeasurement.mm b/ooniprobe/Model/NetworkMeasurement.mm index 78cfc9a11..e13e5e7e5 100644 --- a/ooniprobe/Model/NetworkMeasurement.mm +++ b/ooniprobe/Model/NetworkMeasurement.mm @@ -50,6 +50,7 @@ static void setup_idempotent() { return dns_server; } + @implementation NetworkMeasurement -(id) init { @@ -63,6 +64,8 @@ -(id) init { include_cc = [[[NSUserDefaults standardUserDefaults] objectForKey:@"include_cc"] boolValue]; upload_results = [[[NSUserDefaults standardUserDefaults] objectForKey:@"upload_results"] boolValue]; collector_address = [[NSUserDefaults standardUserDefaults] stringForKey:@"collector_address"]; + max_runtime = [[NSUserDefaults standardUserDefaults] objectForKey:@"max_runtime"]; + self.backgroundTask = UIBackgroundTaskInvalid; return self; } @@ -70,6 +73,16 @@ -(void) run { // Nothing to do here } +- (void)showNotification +{ + UILocalNotification* localNotification = [[UILocalNotification alloc] init]; + localNotification.fireDate = [NSDate date]; + localNotification.timeZone = [NSTimeZone defaultTimeZone]; + localNotification.alertBody = [NSString stringWithFormat:NSLocalizedString(@"finished_running", nil), NSLocalizedString(self.name, nil)]; + [localNotification setApplicationIconBadgeNumber:[[UIApplication sharedApplication] applicationIconBadgeNumber]+1]; + [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification]; +} + -(NSString*) getDate { NSDateFormatter *dateformatter=[[NSDateFormatter alloc]init]; [dateformatter setDateFormat:@"dd-MM-yyyy HH:mm:ss"]; @@ -101,6 +114,26 @@ -(void)writeOrAppend:(NSString*)string{ } } +-(void)updateProgress:(double)prog{ + NSString *os = [NSString stringWithFormat:@"Progress: %.1f%%", prog * 100.0]; + self.progress = prog; + NSLog(@"%@", os); + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:@"reloadTable" object:nil]; + }); +} + +-(void)testEnded{ + NSLog(@"%@ testEnded", self.name); + self.completed = TRUE; + [TestStorage set_completed:self.test_id]; + [self showNotification]; + [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask]; + self.backgroundTask = UIBackgroundTaskInvalid; + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:@"refreshTable" object:self]; + }); +} - (void)encodeWithCoder:(NSCoder *)coder { [coder encodeObject:self.name forKey:@"Test_name"]; @@ -125,7 +158,7 @@ - (id)initWithCoder:(NSCoder *)coder { @end - +//NOT USED @implementation DNSInjection : NetworkMeasurement -(id) init { @@ -134,8 +167,15 @@ -(id) init { return self; } -//NOT USED -- (void) run { +-(void)run{ + self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ + [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask]; + self.backgroundTask = UIBackgroundTaskInvalid; + }]; + [self run_test]; +} + +- (void) run_test { self.test_id = [NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]]; self.json_file = [NSString stringWithFormat:@"test-%@.json", self.test_id]; self.log_file = [NSString stringWithFormat:@"test-%@.log", self.test_id]; @@ -158,30 +198,16 @@ - (void) run { .set_options("collector_base_url", [collector_address UTF8String]) .set_input_filepath([path UTF8String]) .set_output_filepath([[self getFileName:@"json"] UTF8String]) + .set_error_filepath([[self getFileName:@"log"] UTF8String]) .set_verbosity(MK_LOG_INFO) .on_progress([self](double prog, const char *s) { - NSString *os = [NSString stringWithFormat:@"Progress: %.1f%%: %s", prog * 100.0, s]; - self.progress = prog; - NSLog(@"%@", os); - dispatch_async(dispatch_get_main_queue(), ^{ - [[NSNotificationCenter defaultCenter] postNotificationName:@"reloadTable" object:nil]; - }); + [self updateProgress:prog]; }) .on_log([self](uint32_t type, const char *s) { - NSString *current = [NSString stringWithFormat:@"%@: %@", [super getDate], - [NSString stringWithUTF8String:s]]; - NSLog(@"%s", s); - dispatch_async(dispatch_get_main_queue(), ^{ - [self writeOrAppend:current]; - }); + NSLog(@"%s", s); }) .start([self]() { - NSLog(@"dns_injection testEnded"); - dispatch_async(dispatch_get_main_queue(), ^{ - self.completed = TRUE; - [TestStorage set_completed:self.test_id]; - [[NSNotificationCenter defaultCenter] postNotificationName:@"refreshTable" object:self]; - }); + [self testEnded]; }); } @@ -195,7 +221,15 @@ -(id) init { return self; } --(void) run { +-(void)run{ + self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ + [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask]; + self.backgroundTask = UIBackgroundTaskInvalid; + }]; + [self run_test]; +} + +-(void) run_test { self.test_id = [NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]]; self.json_file = [NSString stringWithFormat:@"test-%@.json", self.test_id]; self.log_file = [NSString stringWithFormat:@"test-%@.log", self.test_id]; @@ -215,30 +249,16 @@ -(void) run { .set_options("no_collector", !upload_results) .set_options("collector_base_url", [collector_address UTF8String]) .set_output_filepath([[self getFileName:@"json"] UTF8String]) + .set_error_filepath([[self getFileName:@"log"] UTF8String]) .set_verbosity(MK_LOG_INFO) .on_progress([self](double prog, const char *s) { - NSString *os = [NSString stringWithFormat:@"Progress: %.1f%%: %s", prog * 100.0, s]; - self.progress = prog; - NSLog(@"%@", os); - dispatch_async(dispatch_get_main_queue(), ^{ - [[NSNotificationCenter defaultCenter] postNotificationName:@"reloadTable" object:nil]; - }); + [self updateProgress:prog]; }) .on_log([self](uint32_t type, const char *s) { - NSString *current = [NSString stringWithFormat:@"%@: %@", [super getDate], - [NSString stringWithUTF8String:s]]; - NSLog(@"%s", s); - dispatch_async(dispatch_get_main_queue(), ^{ - [self writeOrAppend:current]; - }); + NSLog(@"%s", s); }) .start([self]() { - NSLog(@"http_invalid_request_line testEnded"); - dispatch_async(dispatch_get_main_queue(), ^{ - self.completed = TRUE; - [TestStorage set_completed:self.test_id]; - [[NSNotificationCenter defaultCenter] postNotificationName:@"refreshTable" object:self]; - }); + [self testEnded]; }); } @@ -253,7 +273,15 @@ -(id) init { return self; } --(void) run { +-(void)run{ + self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ + [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask]; + self.backgroundTask = UIBackgroundTaskInvalid; + }]; + [self run_test]; +} + +-(void) run_test { self.test_id = [NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]]; self.json_file = [NSString stringWithFormat:@"test-%@.json", self.test_id]; self.log_file = [NSString stringWithFormat:@"test-%@.log", self.test_id]; @@ -278,28 +306,13 @@ -(void) run { .set_output_filepath([[self getFileName:@"json"] UTF8String]) .set_verbosity(MK_LOG_INFO) .on_progress([self](double prog, const char *s) { - NSString *os = [NSString stringWithFormat:@"Progress: %.1f%%: %s", prog * 100.0, s]; - self.progress = prog; - NSLog(@"%@", os); - dispatch_async(dispatch_get_main_queue(), ^{ - [[NSNotificationCenter defaultCenter] postNotificationName:@"reloadTable" object:nil]; - }); + [self updateProgress:prog]; }) .on_log([self](uint32_t type, const char *s) { - NSString *current = [NSString stringWithFormat:@"%@: %@", [super getDate], - [NSString stringWithUTF8String:s]]; NSLog(@"%s", s); - dispatch_async(dispatch_get_main_queue(), ^{ - [self writeOrAppend:current]; - }); }) .start([self]() { - NSLog(@"tcp_connect testEnded"); - dispatch_async(dispatch_get_main_queue(), ^{ - self.completed = TRUE; - [TestStorage set_completed:self.test_id]; - [[NSNotificationCenter defaultCenter] postNotificationName:@"refreshTable" object:self]; - }); + [self testEnded]; }); } @@ -313,7 +326,15 @@ -(id) init { return self; } --(void) run { +-(void)run{ + self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ + [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask]; + self.backgroundTask = UIBackgroundTaskInvalid; + }]; + [self run_test]; +} + +-(void) run_test { self.test_id = [NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]]; self.json_file = [NSString stringWithFormat:@"test-%@.json", self.test_id]; self.log_file = [NSString stringWithFormat:@"test-%@.log", self.test_id]; @@ -322,7 +343,7 @@ -(void) run { [TestStorage add_test:self]; setup_idempotent(); NSBundle *bundle = [NSBundle mainBundle]; - NSString *path = [bundle pathForResource:@"urls" ofType:@"txt"]; + NSString *path = [bundle pathForResource:@"global" ofType:@"txt"]; mk::nettests::WebConnectivityTest() .set_options("backend", [WC_BACKEND UTF8String]) .set_options("port", 80) @@ -336,32 +357,19 @@ -(void) run { .set_options("save_real_probe_cc", include_cc) .set_options("no_collector", !upload_results) .set_options("collector_base_url", [collector_address UTF8String]) + .set_options("max_runtime", [max_runtime doubleValue]) .set_input_filepath([path UTF8String]) + .set_error_filepath([[self getFileName:@"log"] UTF8String]) .set_output_filepath([[self getFileName:@"json"] UTF8String]) .set_verbosity(MK_LOG_INFO) .on_progress([self](double prog, const char *s) { - NSString *os = [NSString stringWithFormat:@"Progress: %.1f%%: %s", prog * 100.0, s]; - self.progress = prog; - NSLog(@"%@", os); - dispatch_async(dispatch_get_main_queue(), ^{ - [[NSNotificationCenter defaultCenter] postNotificationName:@"reloadTable" object:nil]; - }); + [self updateProgress:prog]; }) .on_log([self](uint32_t type, const char *s) { - NSString *current = [NSString stringWithFormat:@"%@: %@", [super getDate], - [NSString stringWithUTF8String:s]]; NSLog(@"%s", s); - dispatch_async(dispatch_get_main_queue(), ^{ - [self writeOrAppend:current]; - }); }) .start([self]() { - NSLog(@"web_connectivity testEnded"); - dispatch_async(dispatch_get_main_queue(), ^{ - self.completed = TRUE; - [TestStorage set_completed:self.test_id]; - [[NSNotificationCenter defaultCenter] postNotificationName:@"refreshTable" object:self]; - }); + [self testEnded]; }); } @@ -375,7 +383,15 @@ -(id) init { return self; } --(void) run { +-(void)run{ + self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ + [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask]; + self.backgroundTask = UIBackgroundTaskInvalid; + }]; + [self run_test]; +} + +-(void) run_test { self.test_id = [NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]]; self.json_file = [NSString stringWithFormat:@"test-%@.json", self.test_id]; self.log_file = [NSString stringWithFormat:@"test-%@.log", self.test_id]; @@ -384,24 +400,6 @@ -(void) run { [TestStorage add_test:self]; mk::nettests::NdtTest() .set_options("test_suite", MK_NDT_DOWNLOAD) - .set_verbosity(MK_LOG_INFO) - .set_output_filepath([[self getFileName:@"json"] UTF8String]) - .on_progress([self](double prog, const char *s) { - NSString *os = [NSString stringWithFormat:@"Progress: %.1f%%: %s", prog * 100.0, s]; - self.progress = prog; - NSLog(@"%@", os); - dispatch_async(dispatch_get_main_queue(), ^{ - [[NSNotificationCenter defaultCenter] postNotificationName:@"reloadTable" object:nil]; - }); - }) - .on_log([self](uint32_t type, const char *s) { - NSString *current = [NSString stringWithFormat:@"%@: %@", [super getDate], - [NSString stringWithUTF8String:s]]; - NSLog(@"%s", s); - dispatch_async(dispatch_get_main_queue(), ^{ - [self writeOrAppend:current]; - }); - }) .set_options("net/ca_bundle_path", [ca_cert UTF8String]) .set_options("dns/nameserver", get_dns_server()) .set_options("geoip_country_path", [geoip_country UTF8String]) @@ -411,12 +409,17 @@ -(void) run { .set_options("save_real_probe_cc", include_cc) .set_options("no_collector", !upload_results) .set_options("collector_base_url", [collector_address UTF8String]) + .set_verbosity(MK_LOG_INFO) + .set_output_filepath([[self getFileName:@"json"] UTF8String]) + .set_error_filepath([[self getFileName:@"log"] UTF8String]) + .on_progress([self](double prog, const char *s) { + [self updateProgress:prog]; + }) + .on_log([self](uint32_t type, const char *s) { + NSLog(@"%s", s); + }) .start([self]() { - dispatch_async(dispatch_get_main_queue(), ^{ - self.completed = TRUE; - [TestStorage set_completed:self.test_id]; - [[NSNotificationCenter defaultCenter] postNotificationName:@"refreshTable" object:self]; - }); + [self testEnded]; }); } diff --git a/ooniprobe/PrefixHeader.pch b/ooniprobe/PrefixHeader.pch index 0c05a2a4c..8b9b00bbc 100644 --- a/ooniprobe/PrefixHeader.pch +++ b/ooniprobe/PrefixHeader.pch @@ -10,7 +10,7 @@ // Include any system framework and library headers here that should be included in all compilation units. // You will also need to set the Prefix Header build setting of one or more of your targets to reference this file. -#define WC_BACKEND @"https://a.web-connectivity.th.ooni.io:4442" +#define WC_BACKEND @"https://b.web-connectivity.th.ooni.io" #define HIRL_BACKEND @"http://213.138.109.232/" #define color_ooni_blue [UIColor colorWithRed:4.0/255.0 green:103.0/255.0 blue:153.0/255.0 alpha:1.0] diff --git a/ooniprobe/Resources/fixtures/global.txt b/ooniprobe/Resources/fixtures/global.txt new file mode 100644 index 000000000..b2fc10f43 --- /dev/null +++ b/ooniprobe/Resources/fixtures/global.txt @@ -0,0 +1,1218 @@ +http://666games.net +http://8thstreetlatinas.com +http://911lies.org +http://a1408.g.akamai.net/5/1408/1388/2005110406/1a1a1ad948be278cff2d96046ad90768d848b41947aa1986/sample_sorenson.mov.zip +http://abpr2.railfan.net +http://adium.im +http://adultfriendfinder.com +http://advocacy.globalvoicesonline.org +http://alt.com +http://amphetamines.com +http://anon.inf.tu-dresden.de +http://anonnews.org +http://anonym.to +http://anonymizer.secuser.com +http://anonymouse.org +http://archive.org +http://astalavista.box.sk +http://avaaz.org +http://beeg.com +http://bitcoin.org +http://bittornado.com +http://blackberry.com +http://blog.com +http://blogmarks.net +http://blogspot.com +http://bluehoney.org +http://blueskyswimwear.com +http://bnaibrith.org +http://bravotube.net +http://btggaming.com +http://btguard.com +http://care.org +http://cartercenter.org +http://casino.com +http://ccc.de +http://ccrjustice.org +http://chaos01.ah.to +http://chinadaily.com.cn +http://christwire.org +http://cocaine.org +http://commons.wikimedia.org +http://community.livejournal.com/anorexicqueen/ +http://conan.xxx +http://coolgaylinks.com +http://crackspider.net +http://craigslist.org +http://creativecommons.org +http://cryptome.org +http://cultdeadcow.com +http://cyber.law.harvard.edu +http://dcemail.com +http://de.lirio.us +http://debate.org.uk +http://del.icio.us +http://delicious.com +http://deoxy.org +http://dextroverse.org +http://dictionary.reference.com +http://docs.google.com +http://doctissimo.fr +http://dopplr.com +http://download.cnet.com/freegate/3000-2085_4-10415391.html +http://dreamhost.com +http://duckduckgo.com +http://earth-liberation-front.org +http://ecstasy.org +http://en.wikipedia.org/wiki/the_holocaust +http://evernote.com +http://exscn.net +http://extratorrent.com +http://extratorrent.cc +http://famousnudes.com +http://fark.com +http://feministing.com +http://filestube.com +http://forum.grasscity.com +http://free.translated.net +http://freedns.afraid.org +http://freehomepage.com +http://freenetproject.org +http://friendfinder.com +http://fsrn.org +http://gawker.com +http://gayonthenet.net +http://gayromeo.com +http://gaytoday.com +http://global.nytimes.com/?iht +http://globalvoicesonline.org +http://gmx.com +http://go.com +http://goaskalice.columbia.edu +http://www.grindr.com/ +http://godhatesfags.com +http://groups.google.com +http://groups.msn.com +http://groups.yahoo.com +http://guerrillagirls.com +http://hackers.com +http://hardsextube.com +http://herdict.org +http://heroin.org +http://hidemyass.com +http://hightimes.com +http://hotgaylist.com +http://hotmail.msn.com +http://howtogrowmarijuana.com +http://huffingtonpost.com +http://hulu.com +http://identi.ca +http://imgur.com +http://imp.free.fr +http://instagram.com +http://international.ohmynews.com +http://internet-haganah.com +http://intertran.tranexp.com +http://intertran.tranexp.com/Translate/result.shtml +http://isaalmasih.net +http://islaminstitut.de +http://isohunt.com +http://jdl.org +http://jezebel.com +http://kabobfest.com +http://kat.ph +http://kat.cr +http://khilafah.net +http://kickme.to +http://kickme.to/FOSI +http://kids.yahoo.com +http://last.fm +http://lauraannjacobs.com +http://lesboerotica.net +http://letitbit.net +http://lifestream.aol.com +http://login.live.com +http://mail.lycos.com +http://mail.ru +http://mail.voila.fr +http://mail.walla.co.il +http://mail.yahoo.com +http://mail.yandex.ru +http://manhub.com +http://marijuana.nl +http://masexualite.ca +http://mashable.com +http://members.tripod.com +http://milfhunter.com +http://mixi.jp +http://moqavemat.ir +http://my.myway.com +http://my.myway.com/email_redir.jsp +http://mybloglog.com +http://netflix.com +http://new.gbgm-umc.org +http://news.bbc.co.uk +http://news.google.com +http://ning.com +http://nmap.org +http://oca.org +http://occupystreams.org +http://online.wsj.com +http://openvpn.net +http://opioids.com +http://packetstormsecurity.org +http://peta.xxx +http://phrack.org +http://physiciansforhumanrights.org +http://picasa.google.com +http://pingomatic.com +http://pirateparty.org.au +http://pogo.com +http://pornhub.com +http://postimage.org +http://pridetube.com +http://proxify.com +http://proxpn.com +http://proxytools.sourceforge.net +http://psiphon.ca +http://qibla.com +http://rapidgator.net +http://rarbg.to +http://realdoll.com +http://redtube.com +http://reproductiverights.org +http://rim.net +http://rockettube.com +http://rt.com +http://russia.tv +http://search.aol.com +http://seclists.org +http://seesmic.com +http://www.scruff.com/ +http://sethf.com +http://shamash.org +http://sierraclub.org +http://sites.google.com +http://sourceforge.net/projects/loic/ +http://spaces.msn.com +http://spankwire.com +http://spys.ru +http://steampowered.com +http://survive.org.uk +http://teenadvice.about.com +http://telecomix.org +http://thehackernews.com +http://thepiratebay.org +http://timesofindia.indiatimes.com +http://tinyurl.com +http://tor.eff.org +http://translate.google.com +http://translate.reference.com +http://sakhr.com +http://translation.langenberg.com +http://translation2.paralink.com +http://translator.babylon.com +http://transsexual.org +http://triviasecurity.net +http://turbobit.net +http://tvants.allp2ptv.org +http://tvants.uptodown.com +http://twilight.ws +http://twitpic.com +http://twitter.com +http://twitter.com/anonops +http://twitter.com/youranonnews/ +http://ultrasurf.us +http://uploaded.to +http://vho.org +http://video.google.com +http://vimeo.com +http://voice.yahoo.jajah.com +http://warc.jalb.de +http://wayback.archive.org +http://webbox.com +http://weblogs.us +http://webmail.infomaniak.ch +http://webmail.sso.bluewin.ch +http://whitehonor.com +http://wikia.com +http://wordpress.com +http://wordpress.org +http://worldsingles.com +http://wupj.org +http://www.100webspace.com +http://www.150m.com +http://www.163.com +http://www.1and1.com +http://www.23.org +http://www.2600.org +http://www.2cutelingerie.com +http://www.2ddepot.com +http://www.2shared.com +http://www.365gay.com +http://www.3wishes.com +http://www.43things.com +http://www.4chan.org +http://www.4online-gambling.com +http://www.4shared.com +http://www.888casino.com +http://www.89.com +http://www.911memorial.org +http://www.911truth.org +http://www.abcunderwear.com +http://www.abortionno.org +http://www.absinth.com +http://www.absolut.com +http://www.acdi-cida.gc.ca +http://www.aceshigh.com +http://www.acquisitionx.com +http://www.actionaid.org +http://www.address.com +http://www.adl.org +http://www.adventist.org +http://www.advocate.com +http://www.advocatesforyouth.org +http://www.af.mil +http://www.afp.com +http://www.afterellen.com +http://www.agentprovocateur.com +http://www.ahram.org.eg +http://www.aidsalliance.org +http://www.aidsonline.com +http://www.akdn.org +http://www.alarabiya.net +http://www.aleph.to +http://www.aljazeera.net +http://www.almanar.com.lb +http://www.alqassam.ps +http://www.altavista.com +http://www.altpenis.com +http://www.amateurpages.com +http://www.amazon.com +http://www.americannaziparty.com +http://www.amnesty.org +http://www.ananzi.co.za +http://www.angelfire.com +http://www.angelfire.lycos.com +http://www.anglicancommunion.org +http://www.angryharry.com +http://www.animalliberationfront.com +http://www.anonymitychecker.com +http://www.anonymizer.com +http://www.anonymizer.ru +http://www.anonymsurfen.com +http://www.apple.com +http://www.appzplanet.com +http://www.apt.ch +http://www.arabhra.org +http://www.arablounge.com +http://www.arabnews.com +http://www.arabrenewal.com +http://www.arabtimes.com +http://www.ariannelingerie.com +http://www.army.mil +http://www.article19.org +http://www.aseansec.org +http://www.ashemaletube.com +http://www.asianangels.com +http://www.ask.com +http://www.askmoses.com +http://www.asterisk.org +http://www.atheistalliance.org +http://www.atheists.org +http://www.atimes.com +http://www.attrition.org +http://www.auduboninternational.org +http://www.avert.org +http://www.awid.org +http://www.babylon-x.com +http://www.bacardi.com +http://www.backtrack-linux.org +http://www.bahai.org +http://www.baidu.com +http://www.barmeister.com +http://www.bat.com +http://www.bbc.com/news/ +http://www.bbcworld.com +http://www.bearshare.com +http://www.bebo.com +http://www.beer.com +http://www.beerinfo.com +http://www.bellebound.com +http://www.belmont.ag +http://www.benedelman.org +http://www.betfair.com +http://www.beyondexgay.com +http://www.bfed.info +http://www.bglad.com +http://www.bing.com +http://www.birthcontrol.com +http://www.bisexual.org +http://www.bitcomet.com +http://www.bittorrent.com +http://www.biz.ly +http://www.blackhat.be +http://www.blackjackinfo.com +http://www.blacksandjews.com/Welcome.html +http://www.blizzard.com +http://www.blogeasy.com +http://www.blogger.com +http://www.bloglines.com +http://www.blogsome.com +http://www.blubster.com +http://www.bmezine.com +http://www.bn.com +http://www.bodylingerie.com +http://www.boingboing.net +http://www.breastenlargementmagazine.com +http://www.brinkster.com +http://www.broadvoice.com +http://www.brook.edu +http://www.btselem.org +http://www.buddhanet.net +http://www.budweiser.com +http://www.buydutchseeds.com +http://www.callserve.com +http://www.cameolingerieonline.com +http://www.cancernews.com +http://www.cannabis.com +http://www.cannabis.info +http://www.cannaweed.com +http://www.caritas.org +http://www.carnegieendowment.org +http://www.carnivalcasino.com +http://www.casinotropez.com +http://www.catholic.org +http://www.catholicsforchoice.org +http://www.cbc.ca +http://www.cbsnews.com +http://www.ccel.org +http://www.cdc.gov +http://www.cdt.org +http://www.ceceurope.org +http://www.centcom.mil +http://www.cesr.org +http://www.change.org +http://www.chantelle.com +http://www.childrensdefense.org +http://www.chinatimes.com +http://www.christianity.com +http://www.christianitytoday.com +http://www.churchofeuthanasia.org +http://www.cidh.org +http://www.circumcision.org +http://www.cirp.org +http://www.cis.minsk.by +http://www.cites.org +http://www.citizenlab.org +http://www.clintonfoundation.org +http://www.clubdicecasino.com +http://www.cnn.com +http://www.codespa.org +http://www.collegehumor.com +http://www.common-fund.org +http://www.concern.net +http://www.connotea.org +http://www.convertingtojudaism.com +http://www.copticchurch.net +http://www.coquette.com +http://www.counter-strike.net +http://www.cpj.org +http://www.crackz.ws +http://www.crazyshit.com +http://www.crisisgroup.org +http://www.crs.org +http://www.cseindia.org +http://www.csidonline.org +http://www.csmonitor.com +http://www.cultoferotica.com +http://www.cutegirlfriend.net +http://www.cwgl.rutgers.edu +http://www.cyber-pirates.org +http://www.cypherpunks.ca/otr/ +http://www.dailymail.co.uk +http://www.dailymotion.com +http://www.darknet.org.uk +http://www.darpa.mil +http://www.date.com +http://www.dating.com +http://www.datingdirect.com +http://www.datpiff.com +http://www.dd-rd.ca +http://www.ddo.com +http://www.deathmetal.org +http://www.defcon.org +http://www.defense.gov +http://www.delicates.co.uk +http://www.democracycaucus.net +http://www.democracynow.org +http://www.demonoid.me +http://www.depositfiles.com +http://www.derechos.org +http://www.dfid.gov.uk +http://www.dharmanet.org +http://www.dia.mil +http://www.digg.com +http://www.dit-inc.us +http://www.dmoz.org +http://www.dod.mil +http://www.dogpile.com +http://www.dotster.com +http://www.download.com +http://www.drudgereport.com +http://www.drugs-forum.com +http://www.drugsense.org +http://www.dw-world.de +http://www.ea.com +http://www.earthaction.org +http://www.earthrights.org +http://www.earthwatch.org +http://www.ebaumsworld.com +http://www.ebay.com +http://www.ebuddy.com +http://www.eccentrix.com +http://www.eccouncil.org +http://www.echr.coe.int +http://www.economist.com +http://www.ectaco.com +http://www.ectaco.com/info/software/?atid=2021 +http://www.edf.org +http://www.eea.europa.eu +http://www.eelam.com +http://www.eff.org +http://www.efindlove.com +http://www.efonica.com +http://www.efsha.co.uk +http://www.egyptianislamicgroup.org +http://www.eharmony.com +http://www.eln-voces.com +http://www.eluniversal.com +http://www.emailaddresses.com +http://www.emchurch.org +http://www.emule.com +http://www.engenderhealth.org +http://www.enom.com +http://www.envy.nu +http://www.enzotech.net +http://www.epa.gov +http://www.epic.org +http://www.episcopalchurch.org +http://www.er-d.org +http://www.erogeschichten.com +http://www.erowid.org +http://www.eurogrand.com +http://www.europacasino.com +http://www.euthanasia.cc +http://www.eveonline.com +http://www.excite.com +http://www.exgay.com +http://www.exitinternational.net +http://www.exmormon.org +http://www.facebook.com +http://www.familiesaretalking.org +http://www.familycareintl.org +http://www.famouspornstars.com +http://www.fastmail.fm +http://www.fdf.org +http://www.feedtheminds.org +http://www.femalestars.com +http://www.feminist.com +http://www.feminist.org +http://www.fepproject.org +http://www.fgmnetwork.org +http://www.fhi.org +http://www.fhi.org/en/RH/index.htm +http://www.fidh.org +http://www.figleaves.com +http://www.flickr.com +http://www.flirtylingerie.com +http://www.foe.co.uk +http://www.fordfound.org +http://www.foreignword.com +http://www.foreignword.com/Tools/dictsrch_hp.asp?query=test&src=BP&srcbox=20&trg=BK&submit1=+Go+ +http://www.formercatholic.com +http://www.fotki.com +http://www.fotolog.com +http://www.foxnews.com +http://www.frc.org +http://www.freedomhouse.org +http://www.freedominfo.org +http://www.freeexpression.org +http://www.freegaypornfinder.com +http://www.freegaypornhdtube.com +http://www.freemedia.at +http://www.freemuse.org +http://www.freeservers.com +http://www.freespeech.com +http://www.freespeech.org +http://www.freespeechcoalition.com +http://www.freetranslation.com +http://www.freewebspace.com +http://www.freshpair.com +http://www.friendster.com +http://www.fring.com +http://www.ft.com +http://www.fuckingfreemovies.com +http://www.gambling.com +http://www.gamenode.com +http://www.gamespot.com +http://www.gamingday.com +http://www.gatesfoundation.org +http://www.gay.com +http://www.gayegypt.com +http://www.gayhealth.com +http://www.gayscape.com +http://www.gearthblog.com +http://www.genderandaids.org +http://www.genderhealth.org +http://www.geocities.com +http://www.ghostrecon.com +http://www.giganews.com +http://www.ginvodka.org +http://www.glaad.org +http://www.glbtq.com +http://www.glil.org +http://www.globalfire.tv +http://www.globalfundforwomen.org +http://www.globalpolicy.org +http://www.globet.com +http://www.gmail.com +http://www.gmhc.org +http://www.gn.apc.org +http://www.gnu.org +http://www.gnupg.org +http://www.goarch.org +http://www.godaddy.com +http://www.goldenrivieracasino.com +http://www.google.com +http://www.google.com/search?q=gay +http://www.google.com/search?q=lesbian +http://www.google.com/search?q=transsexual +http://www.gotgayporn.com +http://www.grabit.to +http://www.grandonline.com +http://www.granma.cu +http://www.greenpeace.org +http://www.groupon.com +http://www.guardian.co.uk +http://www.guardster.com +http://www.guildwars.com +http://www.haaretz.com +http://www.habbo.com +http://www.hackcanada.com +http://www.hackforums.net +http://www.hackhull.com +http://www.hacktivismo.com +http://www.hanes.com +http://www.harkatulmujahideen.org +http://www.helvetas.ch +http://www.hereistheporn.com +http://www.heritage.org +http://www.hindunet.org +http://www.hitler.org +http://www.hivaidstribe.com +http://www.hivandhepatitis.com +http://www.hizb-ut-tahrir.org +http://www.hon.ch +http://www.honduras.com +http://www.hospitalityclub.org +http://www.hostgator.com +http://www.hotbot.com +http://www.hotmail.com +http://www.hotspotshield.com +http://www.hrc.org +http://www.hrcr.org +http://www.hrea.org +http://www.hrusa.org +http://www.hrw.org +http://www.http-tunnel.com +http://www.humanrightsfirst.org +http://www.hushmail.com +http://www.hustler.com +http://www.iaffe.org +http://www.iaisite-eng.org +http://www.iaisite.org +http://www.iarf.net +http://www.iavi.org +http://www.icc-cpi.int +http://www.iccwomen.org +http://www.icftu.org +http://www.icj.org +http://www.iconnecthere.com +http://www.icrc.org +http://www.icrw.org +http://www.ict.org.il +http://www.ictj.org +http://www.idea.int +http://www.idrc.ca +http://www.idsoftware.com +http://www.iea.org +http://www.ifad.org +http://www.ifeminists.com +http://www.ifex.org +http://www.ifge.org +http://www.ifj.org +http://www.ifrc.org +http://www.iglhrc.org +http://www.ihf-hr.org +http://www.ihr.org +http://www.ihrc.org +http://www.iico.org +http://www.iicwc.org +http://www.ijm.org +http://www.ikhwanonline.com +http://www.ilga.org +http://www.ilhr.org +http://www.ilo.org +http://www.imageshack.us +http://www.imdb.com +http://www.imesh.com +http://www.imf.org +http://www.implantinfo.com +http://www.inbox.com +http://www.indiatimes.com +http://www.indymedia.org +http://www.inetprivacy.com +http://www.infidels.org +http://www.infowar-monitor.net +http://www.inminds.co.uk +http://www.insecure.org +http://www.interactworldwide.org +http://www.internationalism.org +http://www.interpol.int +http://www.ipcc.ch +http://www.ipetitions.com +http://www.ipvanish.com +http://www.irn.org +http://www.irna.ir +http://www.isiswomen.org +http://www.iskcon.com +http://www.islamdoor.com +http://www.islameyat.com +http://www.islamic-relief.com +http://www.islamicity.com +http://www.islamonline.net +http://www.islamworld.net +http://www.isscr.org +http://www.itsyoursexlife.com +http://www.itunes.com +http://www.iucn.org +http://www.iwantim.com +http://www.iwhc.org +http://www.iyfnet.org +http://www.jackdaniels.com +http://www.jainworld.com +http://www.jdate.com +http://www.jesussaves.cc +http://www.jewwatch.com +http://www.jfcom.mil +http://www.jhr.ca +http://www.jihadwatch.org +http://www.jmarshall.com +http://www.jmarshall.com/tools/cgiproxy/ +http://www.jsf.mil +http://www.judaism.com +http://www.judaismconversion.org +http://www.justice.gov/dea/ +http://www.justicewomen.com +http://www.justin.tv +http://www.kazaa.com +http://www.kbs-frb.be +http://www.kcna.co.jp +http://www.kcna.kp +http://www.keptprivate.com +http://www.khilafah.com +http://www.khrp.org +http://www.kickassclassical.com +http://www.kidshealth.org +http://www.krishna.com +http://www.kurtuluscephesi.com +http://www.laborrights.org +http://www.laborrightsnow.org +http://www.lanacion.com.ar +http://www.lasenza.com +http://www.latimes.com +http://www.latinmail.com +http://www.law-lib.utoronto.ca/Diana/ +http://www.layevangelism.com +http://www.lds.org +http://www.learningpartnership.org +http://www.leaseweb.com +http://www.lemonde.fr +http://www.lesbian.org +http://www.lesbiansubmission.com +http://www.lgf.org.uk +http://www.linay.com +http://www.lineriderfun.com +http://www.lingerieatlarge.com +http://www.lingeriebowl.com +http://www.lingo.com +http://www.linkedin.com +https://www.linkedin.com +http://www.linphone.org +http://www.livejasmin.com +http://www.livejournal.com +http://www.liveleak.com +http://www.luckynugget.com +http://www.luwaran.net +http://www.lycos.com +http://www.lyricwiki.org +http://www.macfound.org +http://www.madre.org +http://www.mail.com +http://www.mail2web.com +http://www.mailinator.com +http://www.mailinator.net +http://www.mainichi.co.jp +http://www.malware.com +http://www.mamma.com +http://www.mariestopes.org.uk +http://www.marijuana.com +http://www.martus.org +http://www.marxists.org +http://www.match.com +http://www.mate1.com +http://www.matrimony.org +http://www.maven.co.il +http://www.meaphone.com +http://www.medecinsdumonde.org +http://www.mediafire.com +http://www.medicinenet.com +http://www.medpot.net +http://www.meetic.com +http://www.mesel-biherat.com +http://www.metacafe.com +http://www.metacrawler.com +http://www.metal-archives.com +http://www.metasploit.org +http://www.michiganmilitia.com +http://www.microsofttranslator.com +http://www.mideastyouth.com +http://www.mininova.org +http://www.minorityrights.org +http://www.mizzima.com +http://www.moderndrunkardmagazine.com +http://www.monacogoldcasino.com +http://www.mormon.org +http://www.mozilla.org +http://www.mp3.com +http://www.msf.org +http://www.msn.com +http://www.muhammadanism.com +http://www.multiproxy.org +http://www.muslimmatrimonial.com +http://www.myspace.com +http://www.mytrans.com.tw +http://www.mywebcalls.com +http://www.namecheap.com +http://www.naral.org +http://www.nato.int +http://www.nature.org +http://www.naughty.com +http://www.navy.mil +http://www.nazarene.org +http://www.nazi-lauck-nsdapao.com +http://www.ncac.org +http://www.ndi.org +http://www.ned.org +http://www.neonjoint.com +http://www.netaddress.com +http://www.netzoola.com +http://www.nmrc.org +http://www.no-ip.com +http://www.no-porn.com +http://www.norml.org +http://www.now.org +http://www.nsa.gov +http://www.nypost.com +http://www.nytimes.com +http://www.ohchr.org +http://www.ohchr.org/english/bodies/hrcouncil/ +http://www.oic-oci.org +http://www.oicc.org +http://www.oikoumene.org +http://www.okcupid.com +http://www.om.org +http://www.omct.org +http://www.on-instant.com +http://www.oneworld.net +http://www.online-dating.org +http://www.online-translator.com +http://www.online-translator.com/text.asp#tr_form +http://www.onlinedating.com +http://www.onlinegambling.com +http://www.onlinewomeninpolitics.org +http://www.onlybingo.com +http://www.oovoo.com +http://www.opec.org +http://www.opendns.com +http://www.opennet.net +http://www.opportunity.org +http://www.originalelf.com +http://www.orthodoxconvert.info +http://www.osce.org +http://www.ou.org +http://www.oxfam.org +http://www.pacom.mil +http://www.paganpride.org +http://www.paltalk.com +http://www.pamperedpassions.com +http://www.panda.org +http://www.pandora.com +http://www.panties.com +http://www.partypoker.com +http://www.partypoker.net +http://www.pass-any-drug-test.com +http://www.pc2call.com +http://www.pcgamer.com +http://www.pcusa.org +http://www.pdhre.org +http://www.peacefire.org +http://www.peacefire.org/circumventor/simple-circumventor-instructions.html +http://www.peakoil.net +http://www.penisbot.com +http://www.pentagon.mil +http://www.penthouse.com +http://www.people.com.cn +http://www.peoplesproxy.com +http://www.perfectmatch.com +http://www.persiankitty.com +http://www.person.com +http://www.peta.org +http://www.pgp.com +http://www.phenoelit.de +http://www.photobucket.com +http://www.piolet.com +http://www.piraten-partei.ch +http://www.piratpartiet.se +http://www.plan-uk.org +http://www.plannedparenthood.org +http://www.playboy.com +http://www.pmi.com +http://www.pof.com +http://www.poker.com +http://www.pokerpages.com +http://www.pokerroom.com +http://www.pokerstars.com +http://www.pokerstars.net +http://www.positive.org +http://www.postcards-for-iran.org +http://www.postmaster.co.uk +http://www.pravda.ru +http://www.premaritalsex.info +http://www.privacyinternational.org +http://www.privaterra.org +http://www.progressio.org.uk +http://www.prolife.com +http://www.prophetofdoom.net +http://www.protectionline.org +http://www.protest.net +http://www.proxyweb.net +http://www.prq.se +http://www.purenudism.net +http://www.purevpn.com +http://www.purextc.com +http://www.quantico.usmc.mil +http://www.queernet.org +http://www.queerty.com +http://www.quran.org +http://www.rackspace.com +http://www.radicalparty.org +http://www.radiofreetexas.org +http://www.radioislam.org +http://www.ragnarokonline.com +http://www.rambler.ru +http://www.ran.org +http://www.rapidshare.de +http://www.rbf.org +http://www.realbeer.com +http://www.realstreaming.net +http://www.reddit.com +http://www.refintl.org +http://www.reliefweb.int +http://www.religiousconsultation.org +http://www.religioustolerance.org +http://www.repubblica.it +http://www.rescue.org +http://www.rfa.org +http://www.rferl.org +http://www.rfi.fr +http://www.riftgame.com +http://www.righttodie.ca +http://www.riverbelle.com +http://www.rockstargames.com +http://www.rollingstone.com +http://www.rollitup.org +http://www.rotten.com +http://www.roulette.sh +http://www.roxypalace.com +http://www.royalvegas.com +http://www.rsf.org +http://www.ruf-ch.org +http://www.runescape.com +http://www.rxmarijuana.com +http://www.samesexmarriage.ca +http://www.satp.org +http://www.satp.org/satporgtp/site.htm +http://www.savethechildren.net +http://www.sbc.net +http://www.scarleteen.com +http://www.schwarzreport.org +http://www.scientology.org +http://www.scribd.com +http://www.sealswcc.com +http://www.search.com +http://www.searchindia.com +http://www.secondlife.com +http://www.sectsco.org/en/ +http://www.securenym.net +http://www.securityfocus.com +http://www.securitytracker.com +http://www.sendspace.com +http://www.sendthisfile.com +http://www.serials.ws +http://www.sex.com +http://www.sexedlibrary.org +http://www.sexetc.org +http://www.sexualhealth.com +http://www.sexualityandu.ca +http://www.sexy-geschichten.at +http://www.sfsi.org +http://www.shareaza.com +http://www.shia.org +http://www.shinto.org +http://www.shroomery.org +http://www.sida.se +http://www.siecus.org +http://www.simplygay.com +http://www.sina.com.cn +http://www.sixapart.com +http://www.skype.com +http://www.slashdot.org +http://www.slideshare.net +http://www.slotland.com +http://www.slsknet.org +http://www.socom.mil +http://www.solicitorsfromhell.com +http://www.soros.org +http://www.sos-reporters.net +http://www.sourceforge.net +http://www.southcom.mil +http://www.spark.com +http://www.speeddater.co.uk +http://www.spinpalace.com +http://www.sportingbet.com +http://www.sportsinteraction.com +http://www.square-enix.com +http://www.state.gov +http://www.state.gov/g/drl/ +http://www.stopstreetharassment.org +http://www.stormfront.org +http://www.stratcom.mil +http://www.strongvpn.com +http://www.stumbleupon.com +http://www.stupidcensorship.com +http://www.submission.org +http://www.systranbox.com +http://www.talafone.com +http://www.tango.me +http://www.technorati.com +http://www.teenhealthfx.com +http://www.teensource.org +http://www.telegraph.co.uk +http://www.terredeshommes.nl +http://www.terrorismfiles.org +http://www.thc.org +http://www.theepochtimes.com +http://www.theglobalfund.org +http://www.thegooddrugsguide.com +http://www.thehacktivist.com +http://www.themwl.org +http://www.thenationalcampaign.org +http://www.theonion.com +http://www.thepinksofa.com +http://www.theregister.co.uk +http://www.tialsoft.com/download/ +http://www.tialsoft.com/multitranse/ +http://www.tmz.com +http://www.tobacco.org +http://www.topcities.com +http://www.topdrawers.com +http://www.torah.org +http://www.towleroad.com +http://www.translate.ru +http://www.transparency.org +http://www.transwhiz.com +http://www.trashy.com +http://www.tripod.lycos.co.uk +http://www.tripod.lycos.com +http://www.true.com +http://www.truecrypt.org +http://www.truthnet.org +http://www.tsroadmap.com +http://www.twistedinternet.com +http://www.twpt.com +http://www.typepad.com +http://www.u4.no +http://www.ucc.org +http://www.ultimate-anonymity.com +http://www.ultimatebirthcontrol.com +http://www.umc.org +http://www.un.int +http://www.un.org +http://www.un.org/docs/sc/ +http://www.un.org/rights/ +http://www.unaids.org +http://www.unep.org +http://www.unfpa.org +http://www.unfpa.org/swp +http://www.unhcr.org +http://www.unicef.org +http://www.unlockme.co.uk +http://www.unpo.org +http://www.unwatch.org +http://www.upci.org +http://www.us.army.mil +http://www.usacasino.com +http://www.usafa.af.mil +http://www.usaid.gov +http://www.uscg.mil +http://www.ushmm.org +http://www.utorrent.com +http://www.vanguardnewsnetwork.com +http://www.vatican.va +http://www.venusswimwear.com +http://www.veoh.com +http://www.vibe.com +http://www.viber.com +http://www.victoriassecret.com +http://www.videogamereview.com +http://www.voanews.com +http://www.voicepulse.com +http://www.volcanomail.com +http://www.vonage.com +http://www.wallpapergate.com +http://www.walmart.com +http://www.warchild.org +http://www.warhammeronline.com +http://www.washingtontimes.com +http://www.watchtower.org +http://www.wcicc.org +http://www.weblogger.com +http://www.webspawner.com +http://www.webwombat.com.au +http://www.wedo.org +http://www.weebly.com +http://www.weedfarmer.com +http://www.weforum.org +http://www.well.com +http://www.well.com/user/queerjhd/ +http://www.wetplace.com +http://www.wftucentral.org +http://www.whatsapp.com +http://www.whitepower.com +http://www.who.int +http://www.who.int/influenza/human_animal_interface +http://www.who.int/reproductivehealth +http://www.who.int/topics/hiv_aids/ +http://www.wiesenthal.com +http://www.wikileaks.org +http://www.wikipedia.org +http://www.wikispaces.com +http://www.wiktionary.org +http://www.wilpf.org +http://www.winespectator.com +http://www.witness.org +http://www.wix.com +http://www.wizards.com +http://www.wkkf.org +http://www.wluml.org +http://www.wmtransfer.com +http://www.wnd.com +http://www.womeninblack.org +http://www.womensmediacenter.com +http://www.womensmediapool.org +http://www.womenwarpeace.org +http://www.wordreference.com +http://www.wordreference.com/enfr/test +http://www.worldbank.org +http://www.worldhealth.net +http://www.worldjewishcongress.org +http://www.worldlingo.com +http://www.worldlingo.com/en/products_services/worldlingo_translator.html +http://www.worldofwarcraft.com +http://www.worldrtd.net +http://www.worldsex.com +http://www.worldwildlife.org +http://www.wzo.org.il +http://www.xanga.com +http://www.xbox.com +http://www.xenu.net +http://www.xfocus.org +http://www.xinhua.org +http://www.xroxy.com +http://www.xxlmag.com +http://www.ya.com +http://www.ya.com/mixmail/ +http://www.yahoo.com +http://www.ymca.int +http://www.youngerbabes.com +http://www.yousendit.com +http://www.youtube.com +http://www.zeit.de +http://www.zensur.freerk.com +http://www.zone-h.org +http://www.zoomshare.com +http://www.zzn.com +http://www1.umn.edu/humanrts/iwraw/ +http://xhamster.com +http://xvideos.com +http://xxx.lanl.gov +http://yelp.com +http://yfrog.com +http://youjizz.com +http://youporn.com +http://zionstrumpet.com +https://addons.mozilla.org +https://addons.mozilla.org/en-US/firefox/addon/4286 +https://citizenlab.org +https://encrypted.google.com +https://foursquare.com +https://gmail.com +https://guardianproject.info +https://login.live.com +https://pinterest.com +https://plus.google.com +https://plus.im +https://riseup.net +https://secure.flickr.com +https://secure.logmein.com +https://spideroak.com +https://t.co +https://thepiratebay.se +https://torrentz.eu +https://twitter.com +https://ultrasurf.us +https://www.accessnow.org +https://www.cia.gov +https://www.dropbox.com +https://www.facebook.com +https://www.google.com +https://www.google.com/transparencyreport/ +https://gpgtools.org +https://www.ipredator.se +https://www.megaproxy.com +https://www.netaddress.com +https://www.outlook.com +https://www.paypal.com +https://www.torproject.org +https://www.transferbigfiles.com +https://www.tumblr.com +https://www.yola.com +https://www.exploit-db.com/ +http://sci-hub.org/ +http://sci-hub.io/ +http://sci-hub.ac/ +http://sci-hub.bz/ +http://sci-hub.cc/ +https://tails.boum.org/ diff --git a/ooniprobe/Resources/fixtures/urls.txt b/ooniprobe/Resources/fixtures/urls.txt deleted file mode 100644 index 31250d2ff..000000000 --- a/ooniprobe/Resources/fixtures/urls.txt +++ /dev/null @@ -1,10 +0,0 @@ -http://torproject.org -http://ooni.nu -http://neubot.org -http://archive.org -http://creativecommons.org -http://cyber.law.harvard.edu -http://duckduckgo.com -http://netflix.com -http://nmap.org -http://www.emule.com diff --git a/ooniprobe/View/Informed consent/IntroductionViewController.m b/ooniprobe/View/Informed consent/IntroductionViewController.m index 92205e680..de5cdf87b 100644 --- a/ooniprobe/View/Informed consent/IntroductionViewController.m +++ b/ooniprobe/View/Informed consent/IntroductionViewController.m @@ -30,4 +30,5 @@ -(IBAction)next{ [self performSegueWithIdentifier:@"toRisks" sender:self]; } + @end diff --git a/ooniprobe/View/SettingsTableViewController.h b/ooniprobe/View/SettingsTableViewController.h index 7fdde8cf8..9e4fd1e58 100644 --- a/ooniprobe/View/SettingsTableViewController.h +++ b/ooniprobe/View/SettingsTableViewController.h @@ -4,9 +4,14 @@ #import -@interface SettingsTableViewController : UITableViewController { +@interface SettingsTableViewController : UITableViewController { NSArray *settingsItems; + NSArray *otherItems; UITextField *value; + UIDatePicker *datePicker; + NSDateFormatter *dateFormatter; + UITextField *timeField; + UIToolbar *keyboardToolbar; } @end diff --git a/ooniprobe/View/SettingsTableViewController.m b/ooniprobe/View/SettingsTableViewController.m index c5a5b7944..3aa4d1ea4 100644 --- a/ooniprobe/View/SettingsTableViewController.m +++ b/ooniprobe/View/SettingsTableViewController.m @@ -3,6 +3,8 @@ // information on the copying conditions. #import "SettingsTableViewController.h" +#define settings 4 +#define notification 1 @interface SettingsTableViewController () @@ -13,9 +15,15 @@ @implementation SettingsTableViewController - (void)viewDidLoad { [super viewDidLoad]; self.title = NSLocalizedString(@"settings", nil); - settingsItems = @[@"include_ip", @"include_asn", @"include_cc", @"upload_results", @"collector_address"]; - //self.tableView.estimatedRowHeight = 80.0; - //self.tableView.rowHeight = UITableViewAutomaticDimension; + [self reloadSettings]; + datePicker = [[UIDatePicker alloc] init]; + [datePicker setDatePickerMode:UIDatePickerModeTime]; + [datePicker setLocale:[NSLocale currentLocale]]; + NSDate *time = [[NSUserDefaults standardUserDefaults] objectForKey:@"local_notifications_time"]; + [datePicker setDate:time]; + [datePicker addTarget:self action:@selector(timeChanged:) forControlEvents:UIControlEventValueChanged]; + dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setDateFormat:@"HH:mm"]; } - (void)didReceiveMemoryWarning { @@ -25,73 +33,134 @@ - (void)didReceiveMemoryWarning { #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 1; + return 3; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return [settingsItems count]; + if (section == 0) + return [settingsItems count]; + else if (section == 1) return [otherItems count]; + return 1; +} + +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section +{ + if (section == 0) + return NSLocalizedString(@"collector_settings", nil); + else if (section == 1) + return NSLocalizedString(@"notifications", nil); + return NSLocalizedString(@"test_limits", nil); } + - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell; - if (indexPath.row < [settingsItems count] -1){ - cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; - NSString *current = [settingsItems objectAtIndex:indexPath.row]; - cell.textLabel.text = NSLocalizedString(current, nil); - UISwitch *switchview = [[UISwitch alloc] initWithFrame:CGRectZero]; - [switchview addTarget:self action:@selector(setSwitch:) forControlEvents:UIControlEventValueChanged]; - if ([[[NSUserDefaults standardUserDefaults] objectForKey:current] boolValue]) switchview.on = YES; - else switchview.on = NO; - cell.accessoryView = switchview; + if (indexPath.section == 0){ + if (indexPath.row < settings){ + cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; + NSString *current = [settingsItems objectAtIndex:indexPath.row]; + cell.textLabel.text = NSLocalizedString(current, nil); + UISwitch *switchview = [[UISwitch alloc] initWithFrame:CGRectZero]; + [switchview addTarget:self action:@selector(setSwitch:) forControlEvents:UIControlEventValueChanged]; + if ([[[NSUserDefaults standardUserDefaults] objectForKey:current] boolValue]) switchview.on = YES; + else switchview.on = NO; + cell.accessoryView = switchview; + } + else { + cell = [tableView dequeueReusableCellWithIdentifier:@"CellSub" forIndexPath:indexPath]; + NSString *current = [settingsItems objectAtIndex:indexPath.row]; + cell.textLabel.text = NSLocalizedString(current, nil); + cell.detailTextLabel.text = [[NSUserDefaults standardUserDefaults] objectForKey:current]; + } } - else { - cell = [tableView dequeueReusableCellWithIdentifier:@"CellSub" forIndexPath:indexPath]; - NSString *current = [settingsItems objectAtIndex:indexPath.row]; - cell.textLabel.text = NSLocalizedString(current, nil); - cell.detailTextLabel.text = [[NSUserDefaults standardUserDefaults] objectForKey:current]; - if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"upload_results"] boolValue]){ - cell.userInteractionEnabled = YES; - cell.hidden = NO; + else if (indexPath.section == 1) { + if (indexPath.row < notification){ + cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; + NSString *current = [otherItems objectAtIndex:indexPath.row]; + cell.textLabel.text = NSLocalizedString(current, nil); + UISwitch *switchview = [[UISwitch alloc] initWithFrame:CGRectZero]; + [switchview addTarget:self action:@selector(setSwitch:) forControlEvents:UIControlEventValueChanged]; + if ([[[NSUserDefaults standardUserDefaults] objectForKey:current] boolValue]) switchview.on = YES; + else switchview.on = NO; + cell.accessoryView = switchview; } else { - cell.userInteractionEnabled = NO; - cell.hidden = YES; + cell = [tableView dequeueReusableCellWithIdentifier:@"CellText" forIndexPath:indexPath]; + NSString *current = [otherItems objectAtIndex:indexPath.row]; + UILabel *title = (UILabel*)[cell viewWithTag:1]; + UITextField *textView = (UITextField*)[cell viewWithTag:2]; + title.text = NSLocalizedString(current, nil); + textView.inputView = datePicker; + NSDate *time = [[NSUserDefaults standardUserDefaults] objectForKey:@"local_notifications_time"]; + textView.text = [dateFormatter stringFromDate:time]; + timeField = textView; } } + else { + cell = [tableView dequeueReusableCellWithIdentifier:@"CellText" forIndexPath:indexPath]; + UILabel *title = (UILabel*)[cell viewWithTag:1]; + UITextField *textView = (UITextField*)[cell viewWithTag:2]; + NSNumber *time = [[NSUserDefaults standardUserDefaults] objectForKey:@"max_runtime"]; + textView.text = [NSString stringWithFormat:@"%@", time]; + title.text = NSLocalizedString(@"max_runtime", nil); + textView.keyboardType = UIKeyboardTypeNumberPad; + textView.delegate = self; + } return cell; } -//TODO not used with uiSwitch --(void) switchRow:(long)idx{ - NSString *current = [settingsItems objectAtIndex:idx]; - if (![[[NSUserDefaults standardUserDefaults] objectForKey:current] boolValue]) - [[NSUserDefaults standardUserDefaults] setBool:YES forKey:current]; - else - [[NSUserDefaults standardUserDefaults] setBool:NO forKey:current]; - [[NSUserDefaults standardUserDefaults] synchronize]; +-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string +{ + NSString * str = [textField.text stringByReplacingCharactersInRange:range withString:string]; + NSNumberFormatter *f = [[NSNumberFormatter alloc] init]; + f.numberStyle = NSNumberFormatterDecimalStyle; + [[NSUserDefaults standardUserDefaults] setObject:[f numberFromString:str] forKey:@"max_runtime"]; + return YES; } -(IBAction)setSwitch:(UISwitch *)mySwitch{ UITableViewCell *cell = (UITableViewCell *)mySwitch.superview; NSIndexPath *indexpath = [self.tableView indexPathForCell:cell]; - NSString *current = [settingsItems objectAtIndex:indexpath.row]; + NSString *current; + if (indexpath.section == 0) + current = [settingsItems objectAtIndex:indexpath.row]; + else + current = [otherItems objectAtIndex:indexpath.row]; if (mySwitch.on) [[NSUserDefaults standardUserDefaults] setBool:YES forKey:current]; else [[NSUserDefaults standardUserDefaults] setBool:NO forKey:current]; + [[NSUserDefaults standardUserDefaults] synchronize]; - if ([current isEqualToString:@"upload_results"]){ - NSIndexPath *indexPath_R = [NSIndexPath indexPathForRow:4 inSection:0]; - [self.tableView beginUpdates]; - [self.tableView reloadRowsAtIndexPaths:@[indexPath_R] withRowAnimation:UITableViewRowAnimationNone]; - [self.tableView endUpdates]; + if ([current isEqualToString:@"upload_results"] || [current isEqualToString:@"local_notifications"]){ + if ([current isEqualToString:@"local_notifications"]) { + if (mySwitch.on) + [self showNotification:nil]; + else + [self cancelScheduledNotifications]; + } + [self reloadSettings]; } [[NSNotificationCenter defaultCenter] postNotificationName:@"loadAvailableMeasurements" object:nil]; } +-(void)reloadSettings { + if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"upload_results"] boolValue]) + settingsItems = @[@"include_ip", @"include_asn", @"include_cc", @"upload_results", @"collector_address"]; + else + settingsItems = @[@"include_ip", @"include_asn", @"include_cc", @"upload_results"]; + + if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"local_notifications"] boolValue]) + otherItems = @[@"local_notifications", @"local_notifications_time"]; + else + otherItems = @[@"local_notifications"]; + [self.tableView reloadData]; +} + + - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - if (indexPath.row == [settingsItems count] -1){ + if (indexPath.section == 0 && indexPath.row == [settingsItems count] -1){ NSString *current = [settingsItems objectAtIndex:indexPath.row]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(current, @"") message:nil delegate:self cancelButtonTitle:NSLocalizedString(@"cancel", @"") otherButtonTitles:NSLocalizedString(@"ok", nil), nil]; alert.tag = indexPath.row; @@ -102,6 +171,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath [value setKeyboardType:UIKeyboardTypeURL]; [alert show]; } + [self.view endEditing:YES]; [tableView deselectRowAtIndexPath:indexPath animated:YES]; } @@ -116,4 +186,29 @@ - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)butto } } +- (void)showNotification:(NSDate*)fireDate +{ + [self cancelScheduledNotifications]; + UILocalNotification* localNotification = [[UILocalNotification alloc] init]; + if (fireDate == nil) fireDate = [[NSUserDefaults standardUserDefaults] objectForKey:@"local_notifications_time"]; + localNotification.fireDate = fireDate; + localNotification.alertBody = NSLocalizedString(@"local_notifications_text", nil); + localNotification.timeZone = [NSTimeZone defaultTimeZone]; + localNotification.repeatInterval = NSCalendarUnitDay; + [[UIApplication sharedApplication] scheduleLocalNotification:localNotification]; +} + +-(void)cancelScheduledNotifications{ + [[UIApplication sharedApplication] cancelAllLocalNotifications]; +} + + +-(void)timeChanged:(UIDatePicker*)sender{ + [[NSUserDefaults standardUserDefaults] setObject:datePicker.date forKey:@"local_notifications_time"]; + [[NSUserDefaults standardUserDefaults] synchronize]; + [timeField setText:[dateFormatter stringFromDate:datePicker.date]]; + [self showNotification:datePicker.date]; +} + + @end diff --git a/ooniprobe/View/ViewController.mm b/ooniprobe/View/ViewController.mm index 9f5db6efb..4d29f2ea1 100644 --- a/ooniprobe/View/ViewController.mm +++ b/ooniprobe/View/ViewController.mm @@ -24,6 +24,12 @@ - (void) viewDidLoad { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loadAvailableMeasurements) name:@"loadAvailableMeasurements" object:nil]; } +/* +-(void)viewWillAppear:(BOOL)animated{ + [super viewWillAppear:animated]; + [self.tableView reloadData]; +}*/ + -(void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; if (![[NSUserDefaults standardUserDefaults] objectForKey:@"first_run"]){ @@ -47,9 +53,12 @@ - (void) loadAvailableMeasurements { -(void)refreshTable:(NSNotification *)notification{ NetworkMeasurement *current = (NetworkMeasurement*)[notification object]; + NSLog(@"finishedNetworkMeasurements: %@", self.finishedNetworkMeasurements); [self.runningMeasurementNames removeObject:current.name]; [self.runningNetworkMeasurements removeObject:current]; - [self.finishedNetworkMeasurements insertObject:current atIndex:0]; + //Temp fix for this GUI + self.finishedNetworkMeasurements = [[TestStorage get_tests_rev] mutableCopy]; + //[self.finishedNetworkMeasurements insertObject:current atIndex:0]; [self.tableView reloadData]; } @@ -231,7 +240,8 @@ -(NSArray*)getItems:(NSString*)json_file{ NSFileManager *fileManager = [NSFileManager defaultManager]; NSString *content = @""; if([fileManager fileExistsAtPath:filePath]) { - content = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:NULL]; + NSError *error; + content = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&error]; //Cut out the last \n if ([content length] > 0) { content = [content substringToIndex:[content length]-1];