Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1cddc796e | ||
|
|
77e20f31f5 | ||
|
|
0175f5390e | ||
|
|
effc305b86 | ||
|
|
c1fe258b0d | ||
|
|
36a8f0b97b | ||
|
|
33b9cab8a8 | ||
|
|
b88874b38b | ||
|
|
f55f3ea32d | ||
|
|
c843bd76a2 | ||
|
|
4dd2339ed8 | ||
|
|
280526bef4 | ||
|
|
34caffd4a7 | ||
|
|
9e19b457e2 | ||
|
|
e6846953b7 | ||
|
|
6d78aeac7b |
@@ -1397,7 +1397,7 @@
|
|||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CODE_SIGN_ENTITLEMENTS = main/main.entitlements;
|
CODE_SIGN_ENTITLEMENTS = main/main.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 28;
|
CURRENT_PROJECT_VERSION = 32;
|
||||||
INFOPLIST_FILE = main/Info.plist;
|
INFOPLIST_FILE = main/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@@ -1416,7 +1416,7 @@
|
|||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CODE_SIGN_ENTITLEMENTS = main/main.entitlements;
|
CODE_SIGN_ENTITLEMENTS = main/main.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 28;
|
CURRENT_PROJECT_VERSION = 32;
|
||||||
INFOPLIST_FILE = main/Info.plist;
|
INFOPLIST_FILE = main/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@@ -1435,7 +1435,7 @@
|
|||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = GlassVPN/GlassVPN.entitlements;
|
CODE_SIGN_ENTITLEMENTS = GlassVPN/GlassVPN.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 28;
|
CURRENT_PROJECT_VERSION = 32;
|
||||||
INFOPLIST_FILE = GlassVPN/Info.plist;
|
INFOPLIST_FILE = GlassVPN/Info.plist;
|
||||||
MARKETING_VERSION = 1.0.0;
|
MARKETING_VERSION = 1.0.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "de.uni-bamberg.psi.AppCheck.VPN";
|
PRODUCT_BUNDLE_IDENTIFIER = "de.uni-bamberg.psi.AppCheck.VPN";
|
||||||
@@ -1453,7 +1453,7 @@
|
|||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = GlassVPN/GlassVPN.entitlements;
|
CODE_SIGN_ENTITLEMENTS = GlassVPN/GlassVPN.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 28;
|
CURRENT_PROJECT_VERSION = 32;
|
||||||
INFOPLIST_FILE = GlassVPN/Info.plist;
|
INFOPLIST_FILE = GlassVPN/Info.plist;
|
||||||
MARKETING_VERSION = 1.0.0;
|
MARKETING_VERSION = 1.0.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "de.uni-bamberg.psi.AppCheck.VPN";
|
PRODUCT_BUNDLE_IDENTIFIER = "de.uni-bamberg.psi.AppCheck.VPN";
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import NetworkExtension
|
import NetworkExtension
|
||||||
|
|
||||||
|
let swcdUserAgent: Data = "User-Agent: swcd".data(using: .ascii)!
|
||||||
fileprivate var hook : GlassVPNHook!
|
fileprivate var hook : GlassVPNHook!
|
||||||
|
|
||||||
// MARK: ObserverFactory
|
// MARK: ObserverFactory
|
||||||
@@ -15,8 +16,18 @@ class LDObserverFactory: ObserverFactory {
|
|||||||
override func signal(_ event: ProxySocketEvent) {
|
override func signal(_ event: ProxySocketEvent) {
|
||||||
switch event {
|
switch event {
|
||||||
case .receivedRequest(let session, let socket):
|
case .receivedRequest(let session, let socket):
|
||||||
|
if socket.isCancelled ||
|
||||||
|
(hook.forceDisconnectUnresolvable && session.ipAddress.isEmpty) {
|
||||||
|
hook.silentlyPrevented(session.host)
|
||||||
|
socket.forceDisconnect()
|
||||||
|
return
|
||||||
|
}
|
||||||
let kill = hook.processDNSRequest(session.host)
|
let kill = hook.processDNSRequest(session.host)
|
||||||
if kill { socket.forceDisconnect() }
|
if kill { socket.forceDisconnect() }
|
||||||
|
case .readData(let data, on: let socket):
|
||||||
|
if hook.forceDisconnectSWCD, data.range(of: swcdUserAgent) != nil {
|
||||||
|
socket.disconnect()
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,3 +53,5 @@ That means, AppCheck does not have to be active in the foreground all the time.
|
|||||||
|
|
||||||
*information will be added soon™*
|
*information will be added soon™*
|
||||||
|
|
||||||
|
For now, go to the results page at [https://appchk.de/](https://appchk.de/).
|
||||||
|
Btw. we are searching for [help](https://appchk.de/help/) on our ongoing research project.
|
||||||
|
|||||||
@@ -30,14 +30,16 @@ struct NotificationBanner {
|
|||||||
img.tintColor = fg
|
img.tintColor = fg
|
||||||
view.addSubview(lbl)
|
view.addSubview(lbl)
|
||||||
view.addSubview(img)
|
view.addSubview(img)
|
||||||
img.anchor([.centerY], to: view.layoutMarginsGuide)
|
img.anchor([.centerY], to: lbl)
|
||||||
lbl.anchor([.top, .bottom, .trailing], to: view.layoutMarginsGuide)
|
lbl.anchor([.bottom, .trailing], to: view.layoutMarginsGuide)
|
||||||
img.widthAnchor =&= 25
|
img.widthAnchor =&= 25
|
||||||
img.heightAnchor =&= 25
|
img.heightAnchor =&= 25
|
||||||
if #available(iOS 11, *) {
|
if #available(iOS 11, *) {
|
||||||
img.leadingAnchor =&= view.layoutMarginsGuide.leadingAnchor
|
img.leadingAnchor =&= view.layoutMarginsGuide.leadingAnchor
|
||||||
|
lbl.topAnchor =&= view.layoutMarginsGuide.topAnchor
|
||||||
} else {
|
} else {
|
||||||
img.leadingAnchor =&= view.leadingAnchor + 8
|
img.leadingAnchor =&= view.leadingAnchor + 8
|
||||||
|
lbl.topAnchor =&= view.topAnchor + 8
|
||||||
}
|
}
|
||||||
lbl.leadingAnchor =&= img.trailingAnchor + 8
|
lbl.leadingAnchor =&= img.trailingAnchor + 8
|
||||||
img.bottomAnchor =<= view.bottomAnchor - 8 | .init(rawValue: 999)
|
img.bottomAnchor =<= view.bottomAnchor - 8 | .init(rawValue: 999)
|
||||||
|
|||||||
@@ -37,6 +37,14 @@ extension PrefsShared {
|
|||||||
get { CurrentRecordingState(rawValue: Int("CurrentlyRecording")) ?? .Off }
|
get { CurrentRecordingState(rawValue: Int("CurrentlyRecording")) ?? .Off }
|
||||||
set { Int("CurrentlyRecording", newValue.rawValue) }
|
set { Int("CurrentlyRecording", newValue.rawValue) }
|
||||||
}
|
}
|
||||||
|
static var ForceDisconnectUnresolvableDNS: Bool {
|
||||||
|
get { PrefsShared.Bool("ForceDisconnectUnresolvableDNS") }
|
||||||
|
set { PrefsShared.Bool("ForceDisconnectUnresolvableDNS", newValue) }
|
||||||
|
}
|
||||||
|
static var ForceDisconnectSWCD: Bool {
|
||||||
|
get { PrefsShared.Bool("ForceDisconnectSWCD") }
|
||||||
|
set { PrefsShared.Bool("ForceDisconnectSWCD", newValue) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -405,7 +405,7 @@ extension SQLiteDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func appBundleList() -> [AppBundleInfo]? {
|
func appBundleList() -> [AppBundleInfo]? {
|
||||||
try? run(sql: "SELECT appid, title, subtitle FROM rec WHERE appid IS NOT NULL GROUP BY appid ORDER BY title ASC;") {
|
try? run(sql: "SELECT appid, title, subtitle FROM rec WHERE appid IS NOT NULL GROUP BY appid ORDER BY lower(title) ASC;") {
|
||||||
allRows($0) {
|
allRows($0) {
|
||||||
AppBundleInfo(col_text($0, 0)!, col_text($0, 1), col_text($0, 2))
|
AppBundleInfo(col_text($0, 0)!, col_text($0, 1), col_text($0, 2))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,11 +33,13 @@ extension FilterOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension Recording {
|
extension Recording {
|
||||||
|
static let minTimeLongTerm: Timestamp = .hours(1)
|
||||||
|
|
||||||
var fallbackTitle: String { get {
|
var fallbackTitle: String { get {
|
||||||
isLongTerm ? "Background Recording" : "Unnamed Recording #\(id)"
|
isLongTerm ? "Background Recording" : "Unnamed Recording #\(id)"
|
||||||
} }
|
} }
|
||||||
var duration: Timestamp { get { (stop ?? .now()) - start } }
|
var duration: Timestamp { get { (stop ?? .now()) - start } }
|
||||||
var isLongTerm: Bool { duration > Timestamp.hours(1) }
|
var isLongTerm: Bool { duration > Recording.minTimeLongTerm }
|
||||||
var isShared: Bool { uploadkey?.count ?? 0 > 0}
|
var isShared: Bool { uploadkey?.count ?? 0 > 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,14 +87,21 @@ struct TimeFormat {
|
|||||||
|
|
||||||
/// Duration string with format `mm:ss` or `mm:ss.SSS`
|
/// Duration string with format `mm:ss` or `mm:ss.SSS`
|
||||||
static func from(_ duration: TimeInterval, millis: Bool = false, hours: Bool = false) -> String {
|
static func from(_ duration: TimeInterval, millis: Bool = false, hours: Bool = false) -> String {
|
||||||
let t = Int(duration)
|
var t = Int(duration)
|
||||||
let min = t / 60
|
var min = t / 60
|
||||||
let sec = t % 60
|
var sec = t % 60
|
||||||
if millis {
|
if millis {
|
||||||
let mil = Int(duration * 1000) % 1000
|
let mil = Int(duration * 1000) % 1000
|
||||||
return String(format: "%02d:%02d.%03d", min, sec, mil)
|
return String(format: "%02d:%02d.%03d", min, sec, mil)
|
||||||
} else if hours {
|
} else if hours {
|
||||||
return String(format: "%02d:%02d:%02d", min / 60, min % 60, sec)
|
if t < Recording.minTimeLongTerm {
|
||||||
|
t = Int(Recording.minTimeLongTerm) - t
|
||||||
|
min = t / 60
|
||||||
|
sec = t % 60
|
||||||
|
return String(format: "-%02d:%02d:%02d", min / 60, min % 60, sec)
|
||||||
|
} else {
|
||||||
|
return String(format: "%02d:%02d:%02d", min / 60, min % 60, sec)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return String(format: "%02d:%02d", min, sec)
|
return String(format: "%02d:%02d", min, sec)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097.2" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="hm5-7q-Zfi">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097.3" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="hm5-7q-Zfi">
|
||||||
<device id="retina4_0" orientation="portrait" appearance="light"/>
|
<device id="retina4_0" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
@@ -128,6 +128,7 @@
|
|||||||
<outlet property="buttonView" destination="La3-9e-6TK" id="UMg-xx-6OV"/>
|
<outlet property="buttonView" destination="La3-9e-6TK" id="UMg-xx-6OV"/>
|
||||||
<outlet property="headerView" destination="ppJ-js-Wwz" id="68u-8M-R2Q"/>
|
<outlet property="headerView" destination="ppJ-js-Wwz" id="68u-8M-R2Q"/>
|
||||||
<outlet property="runningView" destination="9Yj-FX-eFd" id="L2C-YR-2HN"/>
|
<outlet property="runningView" destination="9Yj-FX-eFd" id="L2C-YR-2HN"/>
|
||||||
|
<outlet property="startSegment" destination="2MI-6l-YQt" id="Jun-ct-Xag"/>
|
||||||
<outlet property="stopButton" destination="vAq-EZ-Gmx" id="XiW-1H-I9y"/>
|
<outlet property="stopButton" destination="vAq-EZ-Gmx" id="XiW-1H-I9y"/>
|
||||||
<outlet property="timeLabel" destination="rbR-np-cXD" id="EEe-8F-HT6"/>
|
<outlet property="timeLabel" destination="rbR-np-cXD" id="EEe-8F-HT6"/>
|
||||||
</connections>
|
</connections>
|
||||||
@@ -413,15 +414,15 @@
|
|||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="c0B-OV-ujb">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="c0B-OV-ujb">
|
||||||
<rect key="frame" x="16" y="8" width="33.5" height="20.5"/>
|
<rect key="frame" x="16" y="9" width="33.5" height="20.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Detail" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="4" baselineAdjustment="alignBaselines" adjustsLetterSpacingToFitWidth="YES" adjustsFontSizeToFit="NO" id="sAD-Ns-DV6">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Detail" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="4" baselineAdjustment="alignBaselines" adjustsLetterSpacingToFitWidth="YES" adjustsFontSizeToFit="NO" id="sAD-Ns-DV6">
|
||||||
<rect key="frame" x="16" y="31.5" width="35" height="16"/>
|
<rect key="frame" x="16" y="32.5" width="33" height="14.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<fontDescription key="fontDescription" style="UICTFontTextStyleFootnote"/>
|
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
|
||||||
<color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
@@ -656,6 +657,7 @@ Duration: 60:00</string>
|
|||||||
<outlet property="appIcon" destination="rbW-pK-Kct" id="VlO-fG-y1a"/>
|
<outlet property="appIcon" destination="rbW-pK-Kct" id="VlO-fG-y1a"/>
|
||||||
<outlet property="appTitle" destination="Et0-8d-CId" id="HgD-oI-0J8"/>
|
<outlet property="appTitle" destination="Et0-8d-CId" id="HgD-oI-0J8"/>
|
||||||
<outlet property="buttonCancel" destination="TGg-60-wZW" id="5Ej-7t-jaD"/>
|
<outlet property="buttonCancel" destination="TGg-60-wZW" id="5Ej-7t-jaD"/>
|
||||||
|
<outlet property="buttonFilter" destination="LOr-e7-foG" id="qUx-1k-xJK"/>
|
||||||
<outlet property="buttonSave" destination="rWg-hE-Ydl" id="zfM-kx-erX"/>
|
<outlet property="buttonSave" destination="rWg-hE-Ydl" id="zfM-kx-erX"/>
|
||||||
<outlet property="chooseAppTap" destination="Jab-q2-U9X" id="Tzv-lm-sUm"/>
|
<outlet property="chooseAppTap" destination="Jab-q2-U9X" id="Tzv-lm-sUm"/>
|
||||||
<outlet property="inputDetails" destination="pql-H5-k6U" id="NXm-8f-5E6"/>
|
<outlet property="inputDetails" destination="pql-H5-k6U" id="NXm-8f-5E6"/>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="qdB-ZO-LHY">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097.3" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="qdB-ZO-LHY">
|
||||||
<device id="retina4_0" orientation="portrait" appearance="light"/>
|
<device id="retina4_0" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
@@ -243,25 +243,93 @@
|
|||||||
</tableViewSection>
|
</tableViewSection>
|
||||||
<tableViewSection headerTitle="Advanced Settings" id="Vlg-nm-VB3">
|
<tableViewSection headerTitle="Advanced Settings" id="Vlg-nm-VB3">
|
||||||
<cells>
|
<cells>
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="VnR-9B-1zl">
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" textLabel="rio-m6-pXN" detailTextLabel="rr4-sR-VxD" style="IBUITableViewCellStyleSubtitle" id="pQ5-lm-Rco">
|
||||||
<rect key="frame" x="0.0" y="687.5" width="320" height="44"/>
|
<rect key="frame" x="0.0" y="687.5" width="320" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="VnR-9B-1zl" id="ZTz-vZ-l5p">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="pQ5-lm-Rco" id="52Y-H3-jvJ">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="twS-Ne-dU0">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Force disconnect unresolvable" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="rio-m6-pXN">
|
||||||
|
<rect key="frame" x="16" y="5" width="234" height="20.5"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||||
|
<nil key="textColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="in case DNS returns empty IP" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="rr4-sR-VxD">
|
||||||
|
<rect key="frame" x="16" y="25.5" width="166" height="14.5"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
|
||||||
|
<color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="TSu-IP-KFG">
|
||||||
|
<rect key="frame" x="257" y="6" width="49" height="31"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="togglePreventUnresolvable:" destination="qdB-ZO-LHY" eventType="valueChanged" id="xKv-Hp-Nyq"/>
|
||||||
|
</connections>
|
||||||
|
</switch>
|
||||||
|
</subviews>
|
||||||
|
</tableViewCellContentView>
|
||||||
|
<connections>
|
||||||
|
<outlet property="accessoryView" destination="TSu-IP-KFG" id="VGm-hN-DLK"/>
|
||||||
|
</connections>
|
||||||
|
</tableViewCell>
|
||||||
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" textLabel="x5u-5T-XTO" detailTextLabel="n7p-Ab-69G" style="IBUITableViewCellStyleSubtitle" id="lxs-NQ-Q7V">
|
||||||
|
<rect key="frame" x="0.0" y="731.5" width="320" height="44"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="lxs-NQ-Q7V" id="B1l-cb-yQg">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<subviews>
|
||||||
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Force disconnect swcd" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="x5u-5T-XTO">
|
||||||
|
<rect key="frame" x="16" y="5" width="177" height="20.5"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||||
|
<nil key="textColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="User-Agent: swcd (may affect performance)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="n7p-Ab-69G">
|
||||||
|
<rect key="frame" x="16" y="25.5" width="249.5" height="14.5"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
|
||||||
|
<color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="c5N-PN-qWU">
|
||||||
|
<rect key="frame" x="257" y="6" width="49" height="31"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="togglePreventSWCD:" destination="qdB-ZO-LHY" eventType="valueChanged" id="MAa-5v-djq"/>
|
||||||
|
</connections>
|
||||||
|
</switch>
|
||||||
|
</subviews>
|
||||||
|
</tableViewCellContentView>
|
||||||
|
<connections>
|
||||||
|
<outlet property="accessoryView" destination="c5N-PN-qWU" id="SAN-Q9-VOn"/>
|
||||||
|
</connections>
|
||||||
|
</tableViewCell>
|
||||||
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="Tgc-re-gI7">
|
||||||
|
<rect key="frame" x="0.0" y="775.5" width="320" height="44"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Tgc-re-gI7" id="haV-RB-dEa">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<subviews>
|
||||||
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="vZa-EO-FAZ">
|
||||||
<rect key="frame" x="125" y="7" width="70" height="30"/>
|
<rect key="frame" x="125" y="7" width="70" height="30"/>
|
||||||
<fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/>
|
<fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/>
|
||||||
<state key="normal" title="Export DB"/>
|
<state key="normal" title="Export DB"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="exportDB" destination="qdB-ZO-LHY" eventType="touchUpInside" id="FYN-Zz-UK4"/>
|
<action selector="exportDB" destination="qdB-ZO-LHY" eventType="touchUpInside" id="NPx-9w-ua0"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
</subviews>
|
</subviews>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="twS-Ne-dU0" firstAttribute="centerY" secondItem="ZTz-vZ-l5p" secondAttribute="centerY" id="LgK-8q-r6K"/>
|
<constraint firstItem="vZa-EO-FAZ" firstAttribute="centerX" secondItem="haV-RB-dEa" secondAttribute="centerX" id="h0M-qz-pHV"/>
|
||||||
<constraint firstItem="twS-Ne-dU0" firstAttribute="centerX" secondItem="ZTz-vZ-l5p" secondAttribute="centerX" id="ltC-Ba-Bxr"/>
|
<constraint firstItem="vZa-EO-FAZ" firstAttribute="centerY" secondItem="haV-RB-dEa" secondAttribute="centerY" id="xBJ-94-nJh"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</tableViewCellContentView>
|
</tableViewCellContentView>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
@@ -282,6 +350,8 @@
|
|||||||
<outlet property="cellNotificationConnectionAlert" destination="OTC-Kt-LFT" id="XiG-CC-4lC"/>
|
<outlet property="cellNotificationConnectionAlert" destination="OTC-Kt-LFT" id="XiG-CC-4lC"/>
|
||||||
<outlet property="cellNotificationReminder" destination="jZA-aP-aHG" id="sjo-2s-rqW"/>
|
<outlet property="cellNotificationReminder" destination="jZA-aP-aHG" id="sjo-2s-rqW"/>
|
||||||
<outlet property="cellPrivacyAutoDelete" destination="Qyy-0U-yhd" id="PzN-iv-kFl"/>
|
<outlet property="cellPrivacyAutoDelete" destination="Qyy-0U-yhd" id="PzN-iv-kFl"/>
|
||||||
|
<outlet property="swcdToggle" destination="c5N-PN-qWU" id="qDy-BX-O85"/>
|
||||||
|
<outlet property="unresolvableToggle" destination="TSu-IP-KFG" id="Vdb-cm-Uy2"/>
|
||||||
<outlet property="vpnToggle" destination="ZAz-WT-FDb" id="lGX-J8-WrU"/>
|
<outlet property="vpnToggle" destination="ZAz-WT-FDb" id="lGX-J8-WrU"/>
|
||||||
</connections>
|
</connections>
|
||||||
</tableViewController>
|
</tableViewController>
|
||||||
@@ -364,7 +434,7 @@ If App Badge is enabled, display the letter "1" on the homescreen app icon, as l
|
|||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" id="zaV-mh-eqb">
|
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" id="zaV-mh-eqb">
|
||||||
<rect key="frame" x="252" y="6" width="54" height="31"/>
|
<rect key="frame" x="251" y="6" width="54" height="31"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="toggleAllowRestartReminder:" destination="JYM-cs-i4H" eventType="valueChanged" id="F4e-k2-bni"/>
|
<action selector="toggleAllowRestartReminder:" destination="JYM-cs-i4H" eventType="valueChanged" id="F4e-k2-bni"/>
|
||||||
@@ -391,7 +461,7 @@ If App Badge is enabled, display the letter "1" on the homescreen app icon, as l
|
|||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" id="HaE-En-NH3">
|
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" id="HaE-En-NH3">
|
||||||
<rect key="frame" x="252" y="6" width="54" height="31"/>
|
<rect key="frame" x="251" y="6" width="54" height="31"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="toggleAllowRestartNotify:" destination="JYM-cs-i4H" eventType="valueChanged" id="12C-h5-mrR"/>
|
<action selector="toggleAllowRestartNotify:" destination="JYM-cs-i4H" eventType="valueChanged" id="12C-h5-mrR"/>
|
||||||
@@ -418,7 +488,7 @@ If App Badge is enabled, display the letter "1" on the homescreen app icon, as l
|
|||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" id="N2Q-cU-pkd">
|
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" id="N2Q-cU-pkd">
|
||||||
<rect key="frame" x="252" y="6" width="54" height="31"/>
|
<rect key="frame" x="251" y="6" width="54" height="31"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="toggleAllowRestartBadge:" destination="JYM-cs-i4H" eventType="valueChanged" id="76l-6y-fOu"/>
|
<action selector="toggleAllowRestartBadge:" destination="JYM-cs-i4H" eventType="valueChanged" id="76l-6y-fOu"/>
|
||||||
@@ -476,7 +546,7 @@ If App Badge is enabled, display the letter "1" on the homescreen app icon, as l
|
|||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mTm-Rm-1RQ">
|
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mTm-Rm-1RQ">
|
||||||
<rect key="frame" x="255" y="6" width="49" height="31"/>
|
<rect key="frame" x="255" y="6" width="48" height="31"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="toggleAllowRecordingReminder:" destination="JYM-cs-i4H" eventType="valueChanged" id="unC-Ur-jPM"/>
|
<action selector="toggleAllowRecordingReminder:" destination="JYM-cs-i4H" eventType="valueChanged" id="unC-Ur-jPM"/>
|
||||||
@@ -602,7 +672,7 @@ If App Badge is enabled, display the letter "1" on the homescreen app icon, as l
|
|||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="who-8G-voz">
|
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="who-8G-voz">
|
||||||
<rect key="frame" x="256" y="6" width="48" height="31"/>
|
<rect key="frame" x="256" y="6" width="47" height="31"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="toggleShowNotifications:" destination="D2a-Po-vDU" eventType="valueChanged" id="Thg-6R-7wM"/>
|
<action selector="toggleShowNotifications:" destination="D2a-Po-vDU" eventType="valueChanged" id="Thg-6R-7wM"/>
|
||||||
@@ -832,6 +902,6 @@ If App Badge is enabled, display the letter "1" on the homescreen app icon, as l
|
|||||||
</scenes>
|
</scenes>
|
||||||
<inferredMetricsTieBreakers>
|
<inferredMetricsTieBreakers>
|
||||||
<segue reference="tUF-Kv-koO"/>
|
<segue reference="tUF-Kv-koO"/>
|
||||||
<segue reference="6wc-d1-VYY"/>
|
<segue reference="EzT-Xq-wka"/>
|
||||||
</inferredMetricsTieBreakers>
|
</inferredMetricsTieBreakers>
|
||||||
</document>
|
</document>
|
||||||
|
|||||||
@@ -161,4 +161,12 @@ struct VPNAppMessage {
|
|||||||
static func isRecording(_ state: CurrentRecordingState) -> Self {
|
static func isRecording(_ state: CurrentRecordingState) -> Self {
|
||||||
.init("recording-now:\(state.rawValue)")
|
.init("recording-now:\(state.rawValue)")
|
||||||
}
|
}
|
||||||
|
/// Triggered whenever user taps on the switch in settings
|
||||||
|
static func disconnectUnresolvable(_ state: Bool) -> Self {
|
||||||
|
.init("disconnect-unresolvable:\(state ? 1 : 0)")
|
||||||
|
}
|
||||||
|
/// Triggered whenever user taps on the switch in settings
|
||||||
|
static func disconnectSWCD(_ state: Bool) -> Self {
|
||||||
|
.init("disconnect-swcd:\(state ? 1 : 0)")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ class GlassVPNHook {
|
|||||||
private var cachedNotify: CachedConnectionAlert!
|
private var cachedNotify: CachedConnectionAlert!
|
||||||
private var currentlyRecording: Bool = false
|
private var currentlyRecording: Bool = false
|
||||||
|
|
||||||
|
public var forceDisconnectUnresolvable: Bool = false
|
||||||
|
public var forceDisconnectSWCD: Bool = false
|
||||||
|
|
||||||
|
|
||||||
init() { reset() }
|
init() { reset() }
|
||||||
|
|
||||||
/// Reload from stored settings and rebuilt binary search tree
|
/// Reload from stored settings and rebuilt binary search tree
|
||||||
@@ -18,6 +22,8 @@ class GlassVPNHook {
|
|||||||
setAutoDelete(PrefsShared.AutoDeleteLogsDays)
|
setAutoDelete(PrefsShared.AutoDeleteLogsDays)
|
||||||
cachedNotify = CachedConnectionAlert()
|
cachedNotify = CachedConnectionAlert()
|
||||||
currentlyRecording = PrefsShared.CurrentlyRecording != .Off
|
currentlyRecording = PrefsShared.CurrentlyRecording != .Off
|
||||||
|
forceDisconnectUnresolvable = PrefsShared.ForceDisconnectUnresolvableDNS
|
||||||
|
forceDisconnectSWCD = PrefsShared.ForceDisconnectSWCD
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invalidate auto-delete timer and release stored properties. You should nullify this instance afterwards.
|
/// Invalidate auto-delete timer and release stored properties. You should nullify this instance afterwards.
|
||||||
@@ -28,6 +34,8 @@ class GlassVPNHook {
|
|||||||
autoDeleteTimer?.invalidate()
|
autoDeleteTimer?.invalidate()
|
||||||
cachedNotify = nil
|
cachedNotify = nil
|
||||||
currentlyRecording = false
|
currentlyRecording = false
|
||||||
|
forceDisconnectUnresolvable = false
|
||||||
|
forceDisconnectSWCD = false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call this method from `PacketTunnelProvider.handleAppMessage(_:completionHandler:)`
|
/// Call this method from `PacketTunnelProvider.handleAppMessage(_:completionHandler:)`
|
||||||
@@ -50,6 +58,12 @@ class GlassVPNHook {
|
|||||||
let newState = CurrentRecordingState(rawValue: Int(value) ?? 0)
|
let newState = CurrentRecordingState(rawValue: Int(value) ?? 0)
|
||||||
currentlyRecording = newState != .Off
|
currentlyRecording = newState != .Off
|
||||||
return
|
return
|
||||||
|
case "disconnect-unresolvable":
|
||||||
|
forceDisconnectUnresolvable = value == "1"
|
||||||
|
return
|
||||||
|
case "disconnect-swcd":
|
||||||
|
forceDisconnectSWCD = value == "1"
|
||||||
|
return
|
||||||
default: break
|
default: break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,6 +93,11 @@ class GlassVPNHook {
|
|||||||
return blockActive
|
return blockActive
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func silentlyPrevented(_ domain: String) {
|
||||||
|
// TODO: persist in a separate db/table?
|
||||||
|
NSLog("[VPN.INFO] preventing connection to \(domain)")
|
||||||
|
}
|
||||||
|
|
||||||
/// Build binary tree for reverse DNS lookup
|
/// Build binary tree for reverse DNS lookup
|
||||||
private func reloadDomainFilter() {
|
private func reloadDomainFilter() {
|
||||||
let tmp = AppDB?.loadFilters()?.map({
|
let tmp = AppDB?.loadFilters()?.map({
|
||||||
@@ -133,13 +152,12 @@ class GlassVPNHook {
|
|||||||
@objc private func autoDeleteNow(_ sender: Timer) {
|
@objc private func autoDeleteNow(_ sender: Timer) {
|
||||||
NSLog("[VPN.INFO] Auto-delete old logs")
|
NSLog("[VPN.INFO] Auto-delete old logs")
|
||||||
queue.async {
|
queue.async {
|
||||||
|
guard sender.isValid else { return }
|
||||||
do {
|
do {
|
||||||
try AppDB?.dnsLogsDeleteOlderThan(days: sender.userInfo as! Int)
|
try AppDB?.dnsLogsDeleteOlderThan(days: sender.userInfo as! Int)
|
||||||
} catch {
|
} catch {
|
||||||
NSLog("[VPN.WARN] Couldn't delete logs, will retry in 5 minutes. \(error)")
|
NSLog("[VPN.WARN] Couldn't delete logs, will retry in 5 minutes. \(error)")
|
||||||
if sender.isValid {
|
sender.fireDate = Date().addingTimeInterval(300) // retry in 5 min
|
||||||
sender.fireDate = Date().addingTimeInterval(300) // retry in 5 min
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ class TVCShareRecording : UITableViewController, UITextViewDelegate, VCEditTextD
|
|||||||
|
|
||||||
// vars
|
// vars
|
||||||
var record: Recording!
|
var record: Recording!
|
||||||
private var shareNotes: Bool = false // opt-in
|
private var shareNotes: Bool = true // green switch is more present
|
||||||
private lazy var hasNotes: Bool = (self.record.notes != nil)
|
private lazy var hasNotes: Bool = (self.record.notes != nil)
|
||||||
private lazy var editedNotes: String = self.record.notes ?? ""
|
private lazy var editedNotes: String = self.record.notes ?? ""
|
||||||
private lazy var weekInYear: String = {
|
private lazy var weekInYear: String = {
|
||||||
@@ -86,6 +86,13 @@ class TVCShareRecording : UITableViewController, UITextViewDelegate, VCEditTextD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
|
||||||
|
if motion == .motionShake, let key = record.uploadkey {
|
||||||
|
UIPasteboard.general.string = key
|
||||||
|
banner(.ok, "Copied to clipboard", timeout: 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: - Table Data Source
|
// MARK: - Table Data Source
|
||||||
|
|
||||||
@@ -145,7 +152,7 @@ class TVCShareRecording : UITableViewController, UITextViewDelegate, VCEditTextD
|
|||||||
cell = tableView.dequeueReusableCell(withIdentifier: "shareKeyValueCell")!
|
cell = tableView.dequeueReusableCell(withIdentifier: "shareKeyValueCell")!
|
||||||
let src = dataSourceKeyValue[indexPath.row]
|
let src = dataSourceKeyValue[indexPath.row]
|
||||||
cell.textLabel?.text = src.key
|
cell.textLabel?.text = src.key
|
||||||
let flag = shareNotes && indexPath.row == 4
|
let flag = indexPath.row == 4 && shareNotes && hasNotes
|
||||||
cell.detailTextLabel?.text = flag ? editedNotes : src.value
|
cell.detailTextLabel?.text = flag ? editedNotes : src.value
|
||||||
case 3:
|
case 3:
|
||||||
cell = tableView.dequeueReusableCell(withIdentifier: "shareLogCell")!
|
cell = tableView.dequeueReusableCell(withIdentifier: "shareLogCell")!
|
||||||
@@ -234,8 +241,8 @@ class TVCShareRecording : UITableViewController, UITextViewDelegate, VCEditTextD
|
|||||||
|
|
||||||
// MARK: - Alerts & Banner
|
// MARK: - Alerts & Banner
|
||||||
|
|
||||||
private func banner(_ style: NotificationBanner.Style, _ msg: String) {
|
private func banner(_ style: NotificationBanner.Style, _ msg: String, timeout: TimeInterval = 3) {
|
||||||
NotificationBanner(msg, style: style).present(in: self)
|
NotificationBanner(msg, style: style).present(in: navigationController!, hideAfter: timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func showAlertAvailableSoon(_ urlStr: String, when: Int?) {
|
private func showAlertAvailableSoon(_ urlStr: String, when: Int?) {
|
||||||
|
|||||||
@@ -16,13 +16,18 @@ class VCEditRecording: UIViewController, UITextFieldDelegate, UITextViewDelegate
|
|||||||
@IBOutlet private var noteBottom: NSLayoutConstraint!
|
@IBOutlet private var noteBottom: NSLayoutConstraint!
|
||||||
|
|
||||||
@IBOutlet private var chooseAppTap: UITapGestureRecognizer!
|
@IBOutlet private var chooseAppTap: UITapGestureRecognizer!
|
||||||
|
@IBOutlet private var buttonFilter: UIButton!
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
if deleteOnCancel { // aka newly created
|
if deleteOnCancel { // aka newly created
|
||||||
RecordingsDB.persist(record)
|
let r = record!
|
||||||
if Prefs.RecordingReminder.Enabled {
|
DispatchQueue.global().async {
|
||||||
PushNotification.scheduleRecordingReminder(force: true)
|
RecordingsDB.persist(r)
|
||||||
|
if Prefs.RecordingReminder.Enabled {
|
||||||
|
PushNotification.scheduleRecordingReminder(force: true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
buttonFilter.isHidden = true
|
||||||
// mark as destructive
|
// mark as destructive
|
||||||
buttonCancel.tintColor = .systemRed
|
buttonCancel.tintColor = .systemRed
|
||||||
if #available(iOS 13.0, *) {
|
if #available(iOS 13.0, *) {
|
||||||
|
|||||||
@@ -10,8 +10,10 @@ class VCRecordings: UIViewController, UINavigationControllerDelegate {
|
|||||||
@IBOutlet private var runningView: UIView!
|
@IBOutlet private var runningView: UIView!
|
||||||
@IBOutlet private var timeLabel: UILabel!
|
@IBOutlet private var timeLabel: UILabel!
|
||||||
@IBOutlet private var stopButton: UIButton!
|
@IBOutlet private var stopButton: UIButton!
|
||||||
|
@IBOutlet private var startSegment: UISegmentedControl!
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
|
startSegment.setTitleTextAttributes([NSAttributedString.Key.foregroundColor : UIColor.sysLink], for: .normal)
|
||||||
timeLabel.font = timeLabel.font.monoSpace()
|
timeLabel.font = timeLabel.font.monoSpace()
|
||||||
if let ongoing = RecordingsDB.getCurrent() {
|
if let ongoing = RecordingsDB.getCurrent() {
|
||||||
currentRecording = ongoing
|
currentRecording = ongoing
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class TVCOccurrenceContext: UITableViewController {
|
|||||||
private var copyDomain: String? = nil
|
private var copyDomain: String? = nil
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
|
override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
|
||||||
if cellMenu.start(tableView, indexPath) {
|
if !firstOrLast(indexPath.row), cellMenu.start(tableView, indexPath) {
|
||||||
copyDomain = cellMenu.getSelected(dataSource)?.domain
|
copyDomain = cellMenu.getSelected(dataSource)?.domain
|
||||||
self.becomeFirstResponder()
|
self.becomeFirstResponder()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import UIKit
|
|||||||
class TVCSettings: UITableViewController {
|
class TVCSettings: UITableViewController {
|
||||||
|
|
||||||
@IBOutlet var vpnToggle: UISwitch!
|
@IBOutlet var vpnToggle: UISwitch!
|
||||||
|
@IBOutlet var unresolvableToggle: UISwitch!
|
||||||
|
@IBOutlet var swcdToggle: UISwitch!
|
||||||
@IBOutlet var cellDomainsIgnored: UITableViewCell!
|
@IBOutlet var cellDomainsIgnored: UITableViewCell!
|
||||||
@IBOutlet var cellDomainsBlocked: UITableViewCell!
|
@IBOutlet var cellDomainsBlocked: UITableViewCell!
|
||||||
@IBOutlet var cellPrivacyAutoDelete: UITableViewCell!
|
@IBOutlet var cellPrivacyAutoDelete: UITableViewCell!
|
||||||
@@ -14,6 +16,7 @@ class TVCSettings: UITableViewController {
|
|||||||
reloadVPNState()
|
reloadVPNState()
|
||||||
reloadLoggingFilterUI()
|
reloadLoggingFilterUI()
|
||||||
reloadPrivacyUI()
|
reloadPrivacyUI()
|
||||||
|
reloadAdvancedUI()
|
||||||
NotifyVPNStateChanged.observe(call: #selector(reloadVPNState), on: self)
|
NotifyVPNStateChanged.observe(call: #selector(reloadVPNState), on: self)
|
||||||
NotifyDNSFilterChanged.observe(call: #selector(reloadLoggingFilterUI), on: self)
|
NotifyDNSFilterChanged.observe(call: #selector(reloadLoggingFilterUI), on: self)
|
||||||
}
|
}
|
||||||
@@ -191,6 +194,21 @@ extension TVCSettings {
|
|||||||
// MARK: - Advanced
|
// MARK: - Advanced
|
||||||
|
|
||||||
extension TVCSettings {
|
extension TVCSettings {
|
||||||
|
private func reloadAdvancedUI() {
|
||||||
|
unresolvableToggle.isOn = PrefsShared.ForceDisconnectUnresolvableDNS
|
||||||
|
swcdToggle.isOn = PrefsShared.ForceDisconnectSWCD
|
||||||
|
}
|
||||||
|
|
||||||
|
@IBAction private func togglePreventUnresolvable(_ sender: UISwitch) {
|
||||||
|
PrefsShared.ForceDisconnectUnresolvableDNS = sender.isOn
|
||||||
|
GlassVPN.send(.disconnectUnresolvable(sender.isOn))
|
||||||
|
}
|
||||||
|
|
||||||
|
@IBAction private func togglePreventSWCD(_ sender: UISwitch) {
|
||||||
|
PrefsShared.ForceDisconnectSWCD = sender.isOn
|
||||||
|
GlassVPN.send(.disconnectSWCD(sender.isOn))
|
||||||
|
}
|
||||||
|
|
||||||
@IBAction private func exportDB() {
|
@IBAction private func exportDB() {
|
||||||
AppDB?.vacuum()
|
AppDB?.vacuum()
|
||||||
let sheet = UIActivityViewController(activityItems: [URL.internalDB()], applicationActivities: nil)
|
let sheet = UIActivityViewController(activityItems: [URL.internalDB()], applicationActivities: nil)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# What are Recordings?
|
# What are Recordings?
|
||||||
|
|
||||||
Similar to the default logging, recordings will intercept every request and log it for later review. App recordings are usually 3 – 5 minutes long and cover a single application. You can utilize recordings for App analysis or to get a ground truth on background traffic.
|
Similar to the default logging, recordings will intercept every request and log it for later review. App recordings are usually 1 – 4 minutes long and cover a single application. You can utilize recordings for App analysis or to get a ground truth on background traffic.
|
||||||
|
|
||||||
Optionally, you can help us by providing your app specific recordings. Together with your findings we can create a community driven privacy monitor. The research results will help you and others avoid Apps that unnecessarily share data with third-party providers.
|
Optionally, you can help us by providing your app specific recordings. Together with your findings we can create a community driven privacy monitor. The research results will help you and others avoid Apps that unnecessarily share data with third-party providers.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# How to record?
|
# How to record?
|
||||||
|
|
||||||
Before you begin, there are two types of recordings: app specific recordings and general background activity. The former are usually 3 – 5 minutes long, the latter need to be at least an hour long.
|
Before you begin, there are two types of recordings: app specific recordings and general background activity. The former are usually less than 5 minutes long, the latter must be at least an hour long.
|
||||||
|
|
||||||
### Important notice
|
### Important notice
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user