Put old school MacUI in the attic.

This commit is contained in:
Adam Ierymenko 2021-08-11 13:19:49 -04:00
parent 461810b06a
commit f24afca1ba
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
45 changed files with 2 additions and 7 deletions

View file

@ -0,0 +1,391 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
932D472F1D1CD499004BCFE2 /* ZeroTierIcon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 932D472E1D1CD499004BCFE2 /* ZeroTierIcon.icns */; };
932D47331D1CD861004BCFE2 /* PreferencesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 932D47311D1CD861004BCFE2 /* PreferencesViewController.xib */; };
932D47371D1CDC9B004BCFE2 /* AboutViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 932D47351D1CDC9B004BCFE2 /* AboutViewController.xib */; };
93326BDE1CE7C816005CA2AC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 93326BDD1CE7C816005CA2AC /* Assets.xcassets */; };
93326BE11CE7C816005CA2AC /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 93326BDF1CE7C816005CA2AC /* MainMenu.xib */; };
93326BEB1CE7D9B9005CA2AC /* JoinNetworkViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 93326BE91CE7D9B9005CA2AC /* JoinNetworkViewController.xib */; };
93326BEF1CE7DA30005CA2AC /* ShowNetworksViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 93326BED1CE7DA30005CA2AC /* ShowNetworksViewController.xib */; };
93D1675F1D54191C00330C99 /* NodeStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D1675E1D54191C00330C99 /* NodeStatus.m */; };
93D167621D541BC200330C99 /* ServiceCom.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D167611D541BC200330C99 /* ServiceCom.m */; };
93D167661D54308200330C99 /* Network.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D167651D54308200330C99 /* Network.m */; };
93D167691D57E7EA00330C99 /* AboutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D167681D57E7EA00330C99 /* AboutViewController.m */; };
93D1676D1D57EB8400330C99 /* PreferencesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D1676C1D57EB8400330C99 /* PreferencesViewController.m */; };
93D167701D57FD3800330C99 /* NetworkMonitor.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D1676F1D57FD3800330C99 /* NetworkMonitor.m */; };
93D167731D58093C00330C99 /* NetworkInfoCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D167721D58093C00330C99 /* NetworkInfoCell.m */; };
93D167761D580C3500330C99 /* ShowNetworksViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D167751D580C3500330C99 /* ShowNetworksViewController.m */; };
93D167791D5815E600330C99 /* JoinNetworkViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D167781D5815E600330C99 /* JoinNetworkViewController.m */; };
93D1677C1D58228A00330C99 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D1677B1D58228A00330C99 /* AppDelegate.m */; };
93D1679B1D58300F00330C99 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D1679A1D58300F00330C99 /* main.m */; };
93D1679D1D595F0000330C99 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93D1679C1D595F0000330C99 /* WebKit.framework */; };
93DAFB271D3F0BEE004D5417 /* about.html in Resources */ = {isa = PBXBuildFile; fileRef = 93DAFB261D3F0BEE004D5417 /* about.html */; };
93DAFE4B1CFE53CA00547CC4 /* AuthtokenCopy.m in Sources */ = {isa = PBXBuildFile; fileRef = 93DAFE4A1CFE53CA00547CC4 /* AuthtokenCopy.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
932D472E1D1CD499004BCFE2 /* ZeroTierIcon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = ZeroTierIcon.icns; sourceTree = "<group>"; };
932D47311D1CD861004BCFE2 /* PreferencesViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PreferencesViewController.xib; sourceTree = "<group>"; };
932D47351D1CDC9B004BCFE2 /* AboutViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AboutViewController.xib; sourceTree = "<group>"; };
93326BD81CE7C816005CA2AC /* ZeroTier One.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ZeroTier One.app"; sourceTree = BUILT_PRODUCTS_DIR; };
93326BDD1CE7C816005CA2AC /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
93326BE01CE7C816005CA2AC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
93326BE21CE7C816005CA2AC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
93326BE91CE7D9B9005CA2AC /* JoinNetworkViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = JoinNetworkViewController.xib; sourceTree = "<group>"; };
93326BED1CE7DA30005CA2AC /* ShowNetworksViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ShowNetworksViewController.xib; sourceTree = "<group>"; };
93D1675D1D54191C00330C99 /* NodeStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeStatus.h; sourceTree = "<group>"; };
93D1675E1D54191C00330C99 /* NodeStatus.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NodeStatus.m; sourceTree = "<group>"; };
93D167601D541BC200330C99 /* ServiceCom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServiceCom.h; sourceTree = "<group>"; };
93D167611D541BC200330C99 /* ServiceCom.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ServiceCom.m; sourceTree = "<group>"; };
93D167641D54308200330C99 /* Network.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Network.h; sourceTree = "<group>"; };
93D167651D54308200330C99 /* Network.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Network.m; sourceTree = "<group>"; };
93D167671D57E7EA00330C99 /* AboutViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AboutViewController.h; sourceTree = "<group>"; };
93D167681D57E7EA00330C99 /* AboutViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AboutViewController.m; sourceTree = "<group>"; };
93D1676B1D57EB8400330C99 /* PreferencesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PreferencesViewController.h; sourceTree = "<group>"; };
93D1676C1D57EB8400330C99 /* PreferencesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PreferencesViewController.m; sourceTree = "<group>"; };
93D1676E1D57FD3800330C99 /* NetworkMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkMonitor.h; sourceTree = "<group>"; };
93D1676F1D57FD3800330C99 /* NetworkMonitor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NetworkMonitor.m; sourceTree = "<group>"; };
93D167711D58093C00330C99 /* NetworkInfoCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkInfoCell.h; sourceTree = "<group>"; };
93D167721D58093C00330C99 /* NetworkInfoCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NetworkInfoCell.m; sourceTree = "<group>"; };
93D167741D580C3500330C99 /* ShowNetworksViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShowNetworksViewController.h; sourceTree = "<group>"; };
93D167751D580C3500330C99 /* ShowNetworksViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ShowNetworksViewController.m; sourceTree = "<group>"; };
93D167771D5815E600330C99 /* JoinNetworkViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JoinNetworkViewController.h; sourceTree = "<group>"; };
93D167781D5815E600330C99 /* JoinNetworkViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JoinNetworkViewController.m; sourceTree = "<group>"; };
93D1677A1D58228A00330C99 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
93D1677B1D58228A00330C99 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
93D1679A1D58300F00330C99 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
93D1679C1D595F0000330C99 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
93DAFB261D3F0BEE004D5417 /* about.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = about.html; sourceTree = "<group>"; };
93DAFE4A1CFE53CA00547CC4 /* AuthtokenCopy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AuthtokenCopy.m; sourceTree = "<group>"; };
93DAFE4C1CFE53DA00547CC4 /* AuthtokenCopy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AuthtokenCopy.h; sourceTree = "<group>"; };
C13C72B12527E1B20094F8B4 /* ZeroTier One.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "ZeroTier One.entitlements"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
93326BD51CE7C816005CA2AC /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
93D1679D1D595F0000330C99 /* WebKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
93326BCF1CE7C816005CA2AC = {
isa = PBXGroup;
children = (
93D1679C1D595F0000330C99 /* WebKit.framework */,
93326BDA1CE7C816005CA2AC /* ZeroTier One */,
93326BD91CE7C816005CA2AC /* Products */,
);
sourceTree = "<group>";
};
93326BD91CE7C816005CA2AC /* Products */ = {
isa = PBXGroup;
children = (
93326BD81CE7C816005CA2AC /* ZeroTier One.app */,
);
name = Products;
sourceTree = "<group>";
};
93326BDA1CE7C816005CA2AC /* ZeroTier One */ = {
isa = PBXGroup;
children = (
C13C72B12527E1B20094F8B4 /* ZeroTier One.entitlements */,
932D472E1D1CD499004BCFE2 /* ZeroTierIcon.icns */,
93326BDD1CE7C816005CA2AC /* Assets.xcassets */,
93326BDF1CE7C816005CA2AC /* MainMenu.xib */,
93326BE21CE7C816005CA2AC /* Info.plist */,
93DAFE4A1CFE53CA00547CC4 /* AuthtokenCopy.m */,
93DAFE4C1CFE53DA00547CC4 /* AuthtokenCopy.h */,
93D1676E1D57FD3800330C99 /* NetworkMonitor.h */,
93D1676F1D57FD3800330C99 /* NetworkMonitor.m */,
93DAFB261D3F0BEE004D5417 /* about.html */,
93D1675D1D54191C00330C99 /* NodeStatus.h */,
93D1675E1D54191C00330C99 /* NodeStatus.m */,
93D167601D541BC200330C99 /* ServiceCom.h */,
93D167611D541BC200330C99 /* ServiceCom.m */,
93D167641D54308200330C99 /* Network.h */,
93D167651D54308200330C99 /* Network.m */,
93D167671D57E7EA00330C99 /* AboutViewController.h */,
93D167681D57E7EA00330C99 /* AboutViewController.m */,
932D47351D1CDC9B004BCFE2 /* AboutViewController.xib */,
93D1676B1D57EB8400330C99 /* PreferencesViewController.h */,
93D1676C1D57EB8400330C99 /* PreferencesViewController.m */,
932D47311D1CD861004BCFE2 /* PreferencesViewController.xib */,
93D167711D58093C00330C99 /* NetworkInfoCell.h */,
93D167721D58093C00330C99 /* NetworkInfoCell.m */,
93D167741D580C3500330C99 /* ShowNetworksViewController.h */,
93D167751D580C3500330C99 /* ShowNetworksViewController.m */,
93326BED1CE7DA30005CA2AC /* ShowNetworksViewController.xib */,
93D167771D5815E600330C99 /* JoinNetworkViewController.h */,
93D167781D5815E600330C99 /* JoinNetworkViewController.m */,
93326BE91CE7D9B9005CA2AC /* JoinNetworkViewController.xib */,
93D1677A1D58228A00330C99 /* AppDelegate.h */,
93D1677B1D58228A00330C99 /* AppDelegate.m */,
93D1679A1D58300F00330C99 /* main.m */,
);
path = "ZeroTier One";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
93326BD71CE7C816005CA2AC /* ZeroTier One */ = {
isa = PBXNativeTarget;
buildConfigurationList = 93326BE51CE7C816005CA2AC /* Build configuration list for PBXNativeTarget "ZeroTier One" */;
buildPhases = (
93326BD41CE7C816005CA2AC /* Sources */,
93326BD51CE7C816005CA2AC /* Frameworks */,
93326BD61CE7C816005CA2AC /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = "ZeroTier One";
productName = "ZeroTier One";
productReference = 93326BD81CE7C816005CA2AC /* ZeroTier One.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
93326BD01CE7C816005CA2AC /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0730;
LastUpgradeCheck = 0800;
ORGANIZATIONNAME = "ZeroTier, Inc";
TargetAttributes = {
93326BD71CE7C816005CA2AC = {
CreatedOnToolsVersion = 7.3;
};
};
};
buildConfigurationList = 93326BD31CE7C816005CA2AC /* Build configuration list for PBXProject "ZeroTier One" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
Base,
);
mainGroup = 93326BCF1CE7C816005CA2AC;
productRefGroup = 93326BD91CE7C816005CA2AC /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
93326BD71CE7C816005CA2AC /* ZeroTier One */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
93326BD61CE7C816005CA2AC /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
93DAFB271D3F0BEE004D5417 /* about.html in Resources */,
93326BEF1CE7DA30005CA2AC /* ShowNetworksViewController.xib in Resources */,
932D47371D1CDC9B004BCFE2 /* AboutViewController.xib in Resources */,
93326BEB1CE7D9B9005CA2AC /* JoinNetworkViewController.xib in Resources */,
93326BDE1CE7C816005CA2AC /* Assets.xcassets in Resources */,
93326BE11CE7C816005CA2AC /* MainMenu.xib in Resources */,
932D472F1D1CD499004BCFE2 /* ZeroTierIcon.icns in Resources */,
932D47331D1CD861004BCFE2 /* PreferencesViewController.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
93326BD41CE7C816005CA2AC /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
93D1679B1D58300F00330C99 /* main.m in Sources */,
93D167621D541BC200330C99 /* ServiceCom.m in Sources */,
93D167761D580C3500330C99 /* ShowNetworksViewController.m in Sources */,
93DAFE4B1CFE53CA00547CC4 /* AuthtokenCopy.m in Sources */,
93D167701D57FD3800330C99 /* NetworkMonitor.m in Sources */,
93D1675F1D54191C00330C99 /* NodeStatus.m in Sources */,
93D167691D57E7EA00330C99 /* AboutViewController.m in Sources */,
93D1676D1D57EB8400330C99 /* PreferencesViewController.m in Sources */,
93D1677C1D58228A00330C99 /* AppDelegate.m in Sources */,
93D167731D58093C00330C99 /* NetworkInfoCell.m in Sources */,
93D167661D54308200330C99 /* Network.m in Sources */,
93D167791D5815E600330C99 /* JoinNetworkViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
93326BDF1CE7C816005CA2AC /* MainMenu.xib */ = {
isa = PBXVariantGroup;
children = (
93326BE01CE7C816005CA2AC /* Base */,
);
name = MainMenu.xib;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
93326BE31CE7C816005CA2AC /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.11;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
93326BE41CE7C816005CA2AC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.11;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
};
name = Release;
};
93326BE61CE7C816005CA2AC /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "ZeroTier One/ZeroTier One.entitlements";
CODE_SIGN_IDENTITY = "-";
COMBINE_HIDPI_IMAGES = YES;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = "ZeroTier One/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.10;
PRODUCT_BUNDLE_IDENTIFIER = "com.zerotier.ZeroTier-One";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "ZeroTier One/ZeroTier One-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
93326BE71CE7C816005CA2AC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "ZeroTier One/ZeroTier One.entitlements";
CODE_SIGN_IDENTITY = "-";
COMBINE_HIDPI_IMAGES = YES;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = "ZeroTier One/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.10;
PRODUCT_BUNDLE_IDENTIFIER = "com.zerotier.ZeroTier-One";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "ZeroTier One/ZeroTier One-Bridging-Header.h";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
93326BD31CE7C816005CA2AC /* Build configuration list for PBXProject "ZeroTier One" */ = {
isa = XCConfigurationList;
buildConfigurations = (
93326BE31CE7C816005CA2AC /* Debug */,
93326BE41CE7C816005CA2AC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
93326BE51CE7C816005CA2AC /* Build configuration list for PBXNativeTarget "ZeroTier One" */ = {
isa = XCConfigurationList;
buildConfigurations = (
93326BE61CE7C816005CA2AC /* Debug */,
93326BE71CE7C816005CA2AC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 93326BD01CE7C816005CA2AC /* Project object */;
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:ZeroTier One.xcodeproj">
</FileRef>
</Workspace>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View file

@ -0,0 +1,33 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
#import <WebKit/WebKit.h>
@interface AboutViewController : NSViewController <WebPolicyDelegate>
@property (nonatomic, weak) IBOutlet WebView *webView;
- (void)viewDidLoad;
- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation
request:(NSURLRequest *)request
frame:(WebFrame *)frame
decisionListener:(id<WebPolicyDecisionListener>)listener;
@end

View file

@ -0,0 +1,57 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import "AboutViewController.h"
@interface AboutViewController ()
@end
@implementation AboutViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.webView setWantsLayer:YES];
self.webView.layer.borderWidth = 1.0f;
[self.webView.layer setCornerRadius:1.0f];
self.webView.layer.masksToBounds = YES;
[self.webView.layer setBorderColor:[[NSColor darkGrayColor] CGColor]];
self.webView.policyDelegate = self;
NSBundle *bundle = [NSBundle mainBundle];
NSURL *path = [bundle URLForResource:@"about" withExtension:@"html"];
if(path) {
[self.webView.mainFrame loadRequest:[NSURLRequest requestWithURL:path]];
}
}
- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation
request:(NSURLRequest *)request
frame:(WebFrame *)frame
decisionListener:(id<WebPolicyDecisionListener>)listener
{
if(request.URL != nil && request.URL.host != nil) {
[[NSWorkspace sharedWorkspace] openURL:request.URL];
}
else {
[listener use];
}
}
@end

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10116" systemVersion="15G31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10116"/>
<plugIn identifier="com.apple.WebKitIBPlugin" version="10116"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="AboutViewController" customModule="ZeroTier_One" customModuleProvider="target">
<connections>
<outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
<outlet property="webView" destination="3BS-QW-rZO" id="ucY-A9-7p7"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView id="Hz6-mo-xeY">
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<webView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3BS-QW-rZO">
<rect key="frame" x="20" y="20" width="440" height="440"/>
<webPreferences key="preferences" defaultFontSize="16" defaultFixedFontSize="13" minimumFontSize="0">
<nil key="identifier"/>
</webPreferences>
</webView>
</subviews>
<point key="canvasLocation" x="463" y="570"/>
</customView>
</objects>
</document>

View file

@ -0,0 +1,61 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
@class NetworkMonitor;
@class Network;
@class NodeStatus;
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (weak, nonatomic) IBOutlet NSWindow *window;
@property (nonatomic) NSStatusItem *statusItem;
@property (nonatomic) NSPopover *networkListPopover;
@property (nonatomic) NSPopover *joinNetworkPopover;
@property (nonatomic) NSPopover *preferencesPopover;
@property (nonatomic) NSPopover *aboutPopover;
@property (nonatomic) id transientMonitor;
@property (nonatomic) NetworkMonitor *monitor;
@property (nonatomic) NSMutableArray<Network*> *networks;
@property (nonatomic) NodeStatus *status;
- (void)buildMenu;
- (void)onNetworkListUpdated:(NSNotification*)note;
- (void)onNodeStatusUpdated:(NSNotification*)note;
- (void)showNetworks;
- (void)joinNetwork;
- (void)showPreferences;
- (void)showAbout;
- (void)quit;
- (void)toggleNetwork:(NSMenuItem*)sender;
- (void)copyNodeID;
- (void)closeJoinNetworkPopover;
- (void)darkModeChanged:(NSNotification*)note;
@end

View file

@ -0,0 +1,379 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import "AppDelegate.h"
#import "NetworkMonitor.h"
#import "Network.h"
#import "NodeStatus.h"
#import "JoinNetworkViewController.h"
#import "ShowNetworksViewController.h"
#import "PreferencesViewController.h"
#import "AboutViewController.h"
#import "ServiceCom.h"
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:-2.0f];
self.networkListPopover = [[NSPopover alloc] init];
self.joinNetworkPopover = [[NSPopover alloc] init];
self.preferencesPopover = [[NSPopover alloc] init];
self.aboutPopover = [[NSPopover alloc] init];
self.transientMonitor = nil;
self.monitor = [[NetworkMonitor alloc] init];
self.networks = [NSMutableArray<Network*> array];
self.status = nil;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *defaultsDict = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:@"firstRun"];
[defaults registerDefaults:defaultsDict];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:@selector(onNetworkListUpdated:)
name:NetworkUpdateKey
object:nil];
[nc addObserver:self
selector:@selector(onNodeStatusUpdated:)
name:StatusUpdateKey
object:nil];
NSString *osxMode = [defaults stringForKey:@"AppleInterfaceStyle"];
if(osxMode != nil && [osxMode isEqualToString:@"Dark"]) {
self.statusItem.image = [NSImage imageNamed:@"MenuBarIconMacWhite"];
}
else {
self.statusItem.image = [NSImage imageNamed:@"MenuBarIconMac"];
}
[[NSDistributedNotificationCenter defaultCenter] addObserver:self
selector:@selector(darkModeChanged:)
name:@"AppleInterfaceThemeChangedNotification"
object:nil];
[self buildMenu];
JoinNetworkViewController *jnvc = [[JoinNetworkViewController alloc] initWithNibName:@"JoinNetworkViewController" bundle:nil];
jnvc.appDelegate = self;
self.joinNetworkPopover.contentViewController = jnvc;
self.joinNetworkPopover.behavior = NSPopoverBehaviorTransient;
ShowNetworksViewController *showNetworksView = [[ShowNetworksViewController alloc] initWithNibName:@"ShowNetworksViewController" bundle:nil];
showNetworksView.netMonitor = self.monitor;
self.networkListPopover.contentViewController = showNetworksView;
self.networkListPopover.behavior = NSPopoverBehaviorTransient;
PreferencesViewController *prefsView = [[PreferencesViewController alloc] initWithNibName:@"PreferencesViewController" bundle:nil];
self.preferencesPopover.contentViewController = prefsView;
self.preferencesPopover.behavior = NSPopoverBehaviorTransient;
self.aboutPopover.contentViewController = [[AboutViewController alloc] initWithNibName:@"AboutViewController" bundle:nil];
self.aboutPopover.behavior = NSPopoverBehaviorTransient;
BOOL firstRun = [defaults boolForKey:@"firstRun"];
if(firstRun) {
[defaults setBool:NO forKey:@"firstRun"];
[defaults synchronize];
[prefsView setLaunchAtLoginEnabled:YES];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(2);
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self showAbout];
}];
});
}
[self.monitor updateNetworkInfo];
[self.monitor start];
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSDistributedNotificationCenter defaultCenter] removeObserver:self
name:@"AppleInterfaceThemeChangedNotification"
object:nil];
}
- (void)showNetworks {
NSButton *button = nil;
NSRect frame;
if ([self.statusItem respondsToSelector:@selector(button)]) {
button = self.statusItem.button;
frame = button.bounds;
} else if ([self.statusItem respondsToSelector:@selector(_button)]) {
button = [self.statusItem performSelector:@selector(_button)];
frame = button.bounds;
} else {
NSLog(@"Can't get view. Uh oh.");
return;
}
[self.networkListPopover showRelativeToRect:frame
ofView:button
preferredEdge:NSMinYEdge];
if(self.transientMonitor == nil) {
self.transientMonitor =
[NSEvent addGlobalMonitorForEventsMatchingMask:(NSLeftMouseDown|NSRightMouseDown|NSOtherMouseDown)
handler:^(NSEvent * _Nonnull e) {
[NSEvent removeMonitor:self.transientMonitor];
self.transientMonitor = nil;
[self.networkListPopover close];
}];
}
}
- (void)joinNetwork {
NSButton *button = nil;
NSRect frame;
if ([self.statusItem respondsToSelector:@selector(button)]) {
button = self.statusItem.button;
frame = button.bounds;
} else if ([self.statusItem respondsToSelector:@selector(_button)]) {
button = [self.statusItem performSelector:@selector(_button)];
frame = button.bounds;
} else {
NSLog(@"Can't get view. Uh oh.");
return;
}
[self.joinNetworkPopover showRelativeToRect:button.bounds
ofView:button
preferredEdge:NSMinYEdge];
if(self.transientMonitor == nil) {
self.transientMonitor =
[NSEvent addGlobalMonitorForEventsMatchingMask:(NSLeftMouseDown|NSRightMouseDown|NSOtherMouseDown)
handler:^(NSEvent * _Nonnull e) {
[NSEvent removeMonitor:self.transientMonitor];
self.transientMonitor = nil;
[self.joinNetworkPopover close];
}];
}
}
- (void)showPreferences {
NSButton *button = nil;
NSRect frame;
if ([self.statusItem respondsToSelector:@selector(button)]) {
button = self.statusItem.button;
frame = button.bounds;
} else if ([self.statusItem respondsToSelector:@selector(_button)]) {
button = [self.statusItem performSelector:@selector(_button)];
frame = button.bounds;
} else {
NSLog(@"Can't get view. Uh oh.");
return;
}
[self.preferencesPopover showRelativeToRect:button.bounds
ofView:button
preferredEdge:NSMinYEdge];
if(self.transientMonitor == nil) {
[NSEvent addGlobalMonitorForEventsMatchingMask:(NSLeftMouseDown|NSRightMouseDown|NSOtherMouseDown)
handler:^(NSEvent * _Nonnull e) {
[NSEvent removeMonitor:self.transientMonitor];
self.transientMonitor = nil;
[self.preferencesPopover close];
}];
}
}
- (void)showAbout {
NSButton *button = nil;
NSRect frame;
if ([self.statusItem respondsToSelector:@selector(button)]) {
button = self.statusItem.button;
frame = button.bounds;
} else if ([self.statusItem respondsToSelector:@selector(_button)]) {
button = [self.statusItem performSelector:@selector(_button)];
frame = button.bounds;
} else {
NSLog(@"Can't get view. Uh oh.");
return;
}
[self.aboutPopover showRelativeToRect:button.bounds
ofView:button
preferredEdge:NSMinYEdge];
if(self.transientMonitor == nil) {
[NSEvent addGlobalMonitorForEventsMatchingMask:(NSLeftMouseDown|NSRightMouseDown|NSOtherMouseDown)
handler:^(NSEvent * _Nonnull e) {
[NSEvent removeMonitor:self.transientMonitor];
self.transientMonitor = nil;
[self.aboutPopover close];
}];
}
}
- (void)quit {
[NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
}
- (void)onNetworkListUpdated:(NSNotification*)note {
NSArray<Network*> *netList = [note.userInfo objectForKey:@"networks"];
[(ShowNetworksViewController*)self.networkListPopover.contentViewController setNetworks:netList];
self.networks = [netList mutableCopy];
[self buildMenu];
}
- (void)onNodeStatusUpdated:(NSNotification*)note {
NodeStatus *status = [note.userInfo objectForKey:@"status"];
self.status = status;
[self buildMenu];
}
- (void)buildMenu {
NSMenu *menu = [[NSMenu alloc] init];
if(self.status != nil) {
NSString *nodeId = @"Node ID: ";
nodeId = [nodeId stringByAppendingString:self.status.address];
[menu addItem:[[NSMenuItem alloc] initWithTitle:nodeId
action:@selector(copyNodeID)
keyEquivalent:@""]];
[menu addItem:[NSMenuItem separatorItem]];
}
[menu addItem:[[NSMenuItem alloc] initWithTitle:@"Network Details..."
action:@selector(showNetworks)
keyEquivalent:@"n"]];
[menu addItem:[[NSMenuItem alloc] initWithTitle:@"Join Network..."
action:@selector(joinNetwork)
keyEquivalent:@"j"]];
[menu addItem:[NSMenuItem separatorItem]];
if([self.networks count] > 0) {
for(Network *net in self.networks) {
NSString *nwid = [NSString stringWithFormat:@"%10llx", net.nwid];
NSString *networkName = @"";
if([net.name lengthOfBytesUsingEncoding:NSUTF8StringEncoding] == 0) {
networkName = nwid;
}
else {
networkName = [NSString stringWithFormat:@"%@ (%@)", nwid, net.name];
}
if(net.allowDefault && net.connected) {
networkName = [networkName stringByAppendingString:@" [default]"];
}
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:networkName
action:@selector(toggleNetwork:)
keyEquivalent:@""];
if(net.connected) {
item.state = NSOnState;
}
else {
item.state = NSOffState;
}
item.representedObject = net;
[menu addItem:item];
}
[menu addItem:[NSMenuItem separatorItem]];
}
[menu addItem:[[NSMenuItem alloc] initWithTitle:@"About ZeroTier One..."
action:@selector(showAbout)
keyEquivalent:@""]];
[menu addItem:[[NSMenuItem alloc] initWithTitle:@"Preferences..."
action:@selector(showPreferences)
keyEquivalent:@""]];
[menu addItem:[NSMenuItem separatorItem]];
[menu addItem:[[NSMenuItem alloc] initWithTitle:@"Quit"
action:@selector(quit)
keyEquivalent:@"q"]];
self.statusItem.menu = menu;
}
- (void)toggleNetwork:(NSMenuItem*)sender {
Network *network = sender.representedObject;
NSString *nwid = [NSString stringWithFormat:@"%10llx", network.nwid];
if(network.connected) {
NSError *error = nil;
[[ServiceCom sharedInstance] leaveNetwork:nwid error:&error];
if (error) {
NSAlert *alert = [NSAlert alertWithError:error];
alert.alertStyle = NSCriticalAlertStyle;
[alert addButtonWithTitle:@"Ok"];
[alert runModal];
}
}
else {
NSError *error = nil;
[[ServiceCom sharedInstance] joinNetwork:nwid
allowManaged:network.allowManaged
allowGlobal:network.allowGlobal
allowDefault:(network.allowDefault && ![Network defaultRouteExists:self.networks])
allowDNS:network.allowDNS
error:&error];
if (error) {
NSAlert *alert = [NSAlert alertWithError:error];
alert.alertStyle = NSCriticalAlertStyle;
[alert addButtonWithTitle:@"Ok"];
[alert runModal];
}
}
}
- (void)copyNodeID {
if(self.status != nil) {
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
[pasteboard declareTypes:[NSArray arrayWithObject:NSPasteboardTypeString] owner:nil];
[pasteboard setString:self.status.address forType:NSPasteboardTypeString];
}
}
- (void)darkModeChanged:(NSNotification*)note {
NSString *osxMode = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
if(osxMode != nil && [osxMode isEqualToString:@"Dark"]) {
self.statusItem.image = [NSImage imageNamed:@"MenuBarIconMacWhite"];
}
else {
self.statusItem.image = [NSImage imageNamed:@"MenuBarIconMac"];
}
}
- (void)closeJoinNetworkPopover {
if (self.transientMonitor) {
[NSEvent removeMonitor:self.transientMonitor];
self.transientMonitor = nil;
}
[self.joinNetworkPopover close];
}
@end

View file

@ -0,0 +1,59 @@
{
"images" : [
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "2x"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "ZeroTierIcon512x512.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View file

@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View file

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "mac",
"filename" : "Menubar.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"filename" : "MenuBar@2x.png",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View file

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "mac",
"filename" : "MenubarWhite.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"filename" : "MenubarWhite@2x.png",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View file

@ -0,0 +1,26 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef AuthtokenCopy_h
#define AuthtokenCopy_h
#import <Foundation/Foundation.h>
NSString* getAdminAuthToken(AuthorizationRef authRef);
#endif /* AuthtokenCopy_h */

View file

@ -0,0 +1,97 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Foundation/Foundation.h>
#import "AuthtokenCopy.h"
NSString* getAdminAuthToken(AuthorizationRef authRef) {
char *tool = "/bin/cat";
char *args[] = { "/Library/Application Support/ZeroTier/One/authtoken.secret", NULL};
FILE *pipe = nil;
char token[25];
memset(token, 0, sizeof(char)*25);
OSStatus status = AuthorizationExecuteWithPrivileges(authRef, tool, kAuthorizationFlagDefaults, args, &pipe);
if (status != errAuthorizationSuccess) {
NSLog(@"Reading authtoken failed!");
switch(status) {
case errAuthorizationDenied:
NSLog(@"Autorization Denied");
break;
case errAuthorizationCanceled:
NSLog(@"Authorization Canceled");
break;
case errAuthorizationInternal:
NSLog(@"Authorization Internal");
break;
case errAuthorizationBadAddress:
NSLog(@"Bad Address");
break;
case errAuthorizationInvalidRef:
NSLog(@"Invalid Ref");
break;
case errAuthorizationInvalidSet:
NSLog(@"Invalid Set");
break;
case errAuthorizationInvalidTag:
NSLog(@"Invalid Tag");
break;
case errAuthorizationInvalidFlags:
NSLog(@"Invalid Flags");
break;
case errAuthorizationInvalidPointer:
NSLog(@"Invalid Pointer");
break;
case errAuthorizationToolExecuteFailure:
NSLog(@"Tool Execute Failure");
break;
case errAuthorizationToolEnvironmentError:
NSLog(@"Tool Environment Failure");
break;
case errAuthorizationExternalizeNotAllowed:
NSLog(@"Externalize Not Allowed");
break;
case errAuthorizationInteractionNotAllowed:
NSLog(@"Interaction Not Allowed");
break;
case errAuthorizationInternalizeNotAllowed:
NSLog(@"Internalize Not Allowed");
break;
default:
NSLog(@"Unknown Error");
break;
}
return @"";
}
if(pipe != nil) {
fread(&token, sizeof(char), 24, pipe);
fclose(pipe);
return [NSString stringWithUTF8String:token];
}
return @"";
}

View file

@ -0,0 +1,680 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10116" systemVersion="15G31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10116"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate">
<connections>
<outlet property="window" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/>
</connections>
</customObject>
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
<items>
<menuItem title="ZeroTier One" id="1Xt-HY-uBw">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="ZeroTier One" systemMenu="apple" id="uQy-DD-JDr">
<items>
<menuItem title="About ZeroTier One" id="5kV-Vb-QxS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
<menuItem title="Services" id="NMo-om-nkz">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
<menuItem title="Hide ZeroTier One" keyEquivalent="h" id="Olw-nP-bQN">
<connections>
<action selector="hide:" target="-1" id="PnN-Uc-m68"/>
</connections>
</menuItem>
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
</connections>
</menuItem>
<menuItem title="Show All" id="Kd2-mp-pUS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
<menuItem title="Quit ZeroTier One" keyEquivalent="q" id="4sb-4s-VLi">
<connections>
<action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="File" id="dMs-cI-mzQ">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="File" id="bib-Uj-vzu">
<items>
<menuItem title="New" keyEquivalent="n" id="Was-JA-tGl">
<connections>
<action selector="newDocument:" target="-1" id="4Si-XN-c54"/>
</connections>
</menuItem>
<menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
<connections>
<action selector="openDocument:" target="-1" id="bVn-NM-KNZ"/>
</connections>
</menuItem>
<menuItem title="Open Recent" id="tXI-mr-wws">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ">
<items>
<menuItem title="Clear Menu" id="vNY-rz-j42">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="clearRecentDocuments:" target="-1" id="Daa-9d-B3U"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
<menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
<connections>
<action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/>
</connections>
</menuItem>
<menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV">
<connections>
<action selector="saveDocument:" target="-1" id="teZ-XB-qJY"/>
</connections>
</menuItem>
<menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A">
<connections>
<action selector="saveDocumentAs:" target="-1" id="mDf-zr-I0C"/>
</connections>
</menuItem>
<menuItem title="Revert to Saved" id="KaW-ft-85H">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="aJh-i4-bef"/>
<menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="runPageLayout:" target="-1" id="Din-rz-gC5"/>
</connections>
</menuItem>
<menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS">
<connections>
<action selector="print:" target="-1" id="qaZ-4w-aoO"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Edit" id="5QF-Oa-p0T">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Edit" id="W48-6f-4Dl">
<items>
<menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
<connections>
<action selector="undo:" target="-1" id="M6e-cu-g7V"/>
</connections>
</menuItem>
<menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
<connections>
<action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
<menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
<connections>
<action selector="cut:" target="-1" id="YJe-68-I9s"/>
</connections>
</menuItem>
<menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
<connections>
<action selector="copy:" target="-1" id="G1f-GL-Joy"/>
</connections>
</menuItem>
<menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
<connections>
<action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
</connections>
</menuItem>
<menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
</connections>
</menuItem>
<menuItem title="Delete" id="pa3-QI-u2k">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
</connections>
</menuItem>
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
<connections>
<action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
<menuItem title="Find" id="4EN-yA-p0u">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Find" id="1b7-l0-nxx">
<items>
<menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
<connections>
<action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/>
</connections>
</menuItem>
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/>
</connections>
</menuItem>
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
<connections>
<action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/>
</connections>
</menuItem>
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
<connections>
<action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/>
</connections>
</menuItem>
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
<connections>
<action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/>
</connections>
</menuItem>
<menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
<connections>
<action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
<items>
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
<connections>
<action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/>
</connections>
</menuItem>
<menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
<connections>
<action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
<menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/>
</connections>
</menuItem>
<menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/>
</connections>
</menuItem>
<menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Substitutions" id="9ic-FL-obx">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
<items>
<menuItem title="Show Substitutions" id="z6F-FW-3nz">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
<menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/>
</connections>
</menuItem>
<menuItem title="Smart Quotes" id="hQb-2v-fYv">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/>
</connections>
</menuItem>
<menuItem title="Smart Dashes" id="rgM-f4-ycn">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/>
</connections>
</menuItem>
<menuItem title="Smart Links" id="cwL-P1-jid">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/>
</connections>
</menuItem>
<menuItem title="Data Detectors" id="tRr-pd-1PS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/>
</connections>
</menuItem>
<menuItem title="Text Replacement" id="HFQ-gK-NFA">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Transformations" id="2oI-Rn-ZJC">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Transformations" id="c8a-y6-VQd">
<items>
<menuItem title="Make Upper Case" id="vmV-6d-7jI">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/>
</connections>
</menuItem>
<menuItem title="Make Lower Case" id="d9M-CD-aMd">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/>
</connections>
</menuItem>
<menuItem title="Capitalize" id="UEZ-Bs-lqG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Speech" id="xrE-MZ-jX0">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Speech" id="3rS-ZA-NoH">
<items>
<menuItem title="Start Speaking" id="Ynk-f8-cLZ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/>
</connections>
</menuItem>
<menuItem title="Stop Speaking" id="Oyz-dy-DGm">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Format" id="jxT-CU-nIS">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Format" id="GEO-Iw-cKr">
<items>
<menuItem title="Font" id="Gi5-1S-RQB">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Font" systemMenu="font" id="aXa-aM-Jaq">
<items>
<menuItem title="Show Fonts" keyEquivalent="t" id="Q5e-8K-NDq">
<connections>
<action selector="orderFrontFontPanel:" target="YLy-65-1bz" id="WHr-nq-2xA"/>
</connections>
</menuItem>
<menuItem title="Bold" tag="2" keyEquivalent="b" id="GB9-OM-e27">
<connections>
<action selector="addFontTrait:" target="YLy-65-1bz" id="hqk-hr-sYV"/>
</connections>
</menuItem>
<menuItem title="Italic" tag="1" keyEquivalent="i" id="Vjx-xi-njq">
<connections>
<action selector="addFontTrait:" target="YLy-65-1bz" id="IHV-OB-c03"/>
</connections>
</menuItem>
<menuItem title="Underline" keyEquivalent="u" id="WRG-CD-K1S">
<connections>
<action selector="underline:" target="-1" id="FYS-2b-JAY"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="5gT-KC-WSO"/>
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="Ptp-SP-VEL">
<connections>
<action selector="modifyFont:" target="YLy-65-1bz" id="Uc7-di-UnL"/>
</connections>
</menuItem>
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="i1d-Er-qST">
<connections>
<action selector="modifyFont:" target="YLy-65-1bz" id="HcX-Lf-eNd"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kx3-Dk-x3B"/>
<menuItem title="Kern" id="jBQ-r6-VK2">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Kern" id="tlD-Oa-oAM">
<items>
<menuItem title="Use Default" id="GUa-eO-cwY">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useStandardKerning:" target="-1" id="6dk-9l-Ckg"/>
</connections>
</menuItem>
<menuItem title="Use None" id="cDB-IK-hbR">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="turnOffKerning:" target="-1" id="U8a-gz-Maa"/>
</connections>
</menuItem>
<menuItem title="Tighten" id="46P-cB-AYj">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="tightenKerning:" target="-1" id="hr7-Nz-8ro"/>
</connections>
</menuItem>
<menuItem title="Loosen" id="ogc-rX-tC1">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="loosenKerning:" target="-1" id="8i4-f9-FKE"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Ligatures" id="o6e-r0-MWq">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Ligatures" id="w0m-vy-SC9">
<items>
<menuItem title="Use Default" id="agt-UL-0e3">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useStandardLigatures:" target="-1" id="7uR-wd-Dx6"/>
</connections>
</menuItem>
<menuItem title="Use None" id="J7y-lM-qPV">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="turnOffLigatures:" target="-1" id="iX2-gA-Ilz"/>
</connections>
</menuItem>
<menuItem title="Use All" id="xQD-1f-W4t">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useAllLigatures:" target="-1" id="KcB-kA-TuK"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Baseline" id="OaQ-X3-Vso">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Baseline" id="ijk-EB-dga">
<items>
<menuItem title="Use Default" id="3Om-Ey-2VK">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unscript:" target="-1" id="0vZ-95-Ywn"/>
</connections>
</menuItem>
<menuItem title="Superscript" id="Rqc-34-cIF">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="superscript:" target="-1" id="3qV-fo-wpU"/>
</connections>
</menuItem>
<menuItem title="Subscript" id="I0S-gh-46l">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="subscript:" target="-1" id="Q6W-4W-IGz"/>
</connections>
</menuItem>
<menuItem title="Raise" id="2h7-ER-AoG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="raiseBaseline:" target="-1" id="4sk-31-7Q9"/>
</connections>
</menuItem>
<menuItem title="Lower" id="1tx-W0-xDw">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowerBaseline:" target="-1" id="OF1-bc-KW4"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="Ndw-q3-faq"/>
<menuItem title="Show Colors" keyEquivalent="C" id="bgn-CT-cEk">
<connections>
<action selector="orderFrontColorPanel:" target="-1" id="mSX-Xz-DV3"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="iMs-zA-UFJ"/>
<menuItem title="Copy Style" keyEquivalent="c" id="5Vv-lz-BsD">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="copyFont:" target="-1" id="GJO-xA-L4q"/>
</connections>
</menuItem>
<menuItem title="Paste Style" keyEquivalent="v" id="vKC-jM-MkH">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteFont:" target="-1" id="JfD-CL-leO"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Text" id="Fal-I4-PZk">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Text" id="d9c-me-L2H">
<items>
<menuItem title="Align Left" keyEquivalent="{" id="ZM1-6Q-yy1">
<connections>
<action selector="alignLeft:" target="-1" id="zUv-R1-uAa"/>
</connections>
</menuItem>
<menuItem title="Center" keyEquivalent="|" id="VIY-Ag-zcb">
<connections>
<action selector="alignCenter:" target="-1" id="spX-mk-kcS"/>
</connections>
</menuItem>
<menuItem title="Justify" id="J5U-5w-g23">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="alignJustified:" target="-1" id="ljL-7U-jND"/>
</connections>
</menuItem>
<menuItem title="Align Right" keyEquivalent="}" id="wb2-vD-lq4">
<connections>
<action selector="alignRight:" target="-1" id="r48-bG-YeY"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="4s2-GY-VfK"/>
<menuItem title="Writing Direction" id="H1b-Si-o9J">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Writing Direction" id="8mr-sm-Yjd">
<items>
<menuItem title="Paragraph" enabled="NO" id="ZvO-Gk-QUH">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="YGs-j5-SAR">
<string key="title"> Default</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionNatural:" target="-1" id="qtV-5e-UBP"/>
</connections>
</menuItem>
<menuItem id="Lbh-J2-qVU">
<string key="title"> Left to Right</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionLeftToRight:" target="-1" id="S0X-9S-QSf"/>
</connections>
</menuItem>
<menuItem id="jFq-tB-4Kx">
<string key="title"> Right to Left</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionRightToLeft:" target="-1" id="5fk-qB-AqJ"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="swp-gr-a21"/>
<menuItem title="Selection" enabled="NO" id="cqv-fj-IhA">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="Nop-cj-93Q">
<string key="title"> Default</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionNatural:" target="-1" id="lPI-Se-ZHp"/>
</connections>
</menuItem>
<menuItem id="BgM-ve-c93">
<string key="title"> Left to Right</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionLeftToRight:" target="-1" id="caW-Bv-w94"/>
</connections>
</menuItem>
<menuItem id="RB4-Sm-HuC">
<string key="title"> Right to Left</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionRightToLeft:" target="-1" id="EXD-6r-ZUu"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="fKy-g9-1gm"/>
<menuItem title="Show Ruler" id="vLm-3I-IUL">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleRuler:" target="-1" id="FOx-HJ-KwY"/>
</connections>
</menuItem>
<menuItem title="Copy Ruler" keyEquivalent="c" id="MkV-Pr-PK5">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="copyRuler:" target="-1" id="71i-fW-3W2"/>
</connections>
</menuItem>
<menuItem title="Paste Ruler" keyEquivalent="v" id="LVM-kO-fVI">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="pasteRuler:" target="-1" id="cSh-wd-qM2"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="View" id="H8h-7b-M4v">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="View" id="HyV-fh-RgO">
<items>
<menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="toggleToolbarShown:" target="-1" id="BXY-wc-z0C"/>
</connections>
</menuItem>
<menuItem title="Customize Toolbar…" id="1UK-8n-QPP">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="runToolbarCustomizationPalette:" target="-1" id="pQI-g3-MTW"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Window" id="aUF-d1-5bR">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
<items>
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
<connections>
<action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
</connections>
</menuItem>
<menuItem title="Zoom" id="R4o-n2-Eq4">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Help" id="wpr-3q-Mcd">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
<items>
<menuItem title="ZeroTier One Help" keyEquivalent="?" id="FKE-Sm-Kum">
<connections>
<action selector="showHelp:" target="-1" id="y7X-2Q-9no"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<window title="ZeroTier One" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="QvC-M9-y7g">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="335" y="390" width="480" height="360"/>
<rect key="screenRect" x="0.0" y="0.0" width="1716" height="1024"/>
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
<autoresizingMask key="autoresizingMask"/>
</view>
</window>
</objects>
</document>

View file

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string>ZeroTierIcon.icns</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>15</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>LSUIElement</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2016 ZeroTier, Inc. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View file

@ -0,0 +1,41 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
extern NSString * const JoinedNetworksKey;
@class AppDelegate;
@interface JoinNetworkViewController : NSViewController <NSComboBoxDelegate, NSComboBoxDataSource>
@property (nonatomic, weak) IBOutlet NSComboBox *network;
@property (nonatomic, weak) IBOutlet NSButton *joinButton;
@property (nonatomic, weak) IBOutlet NSButton *allowManagedCheckBox;
@property (nonatomic, weak) IBOutlet NSButton *allowGlobalCheckBox;
@property (nonatomic, weak) IBOutlet NSButton *allowDefaultCheckBox;
@property (nonatomic, weak) IBOutlet NSButton *allowDNSCheckBox;
@property (nonatomic, weak) IBOutlet AppDelegate *appDelegate;
@property (nonatomic) NSMutableArray<NSString*> *values;
- (IBAction)onJoinClicked:(id)sender;
@end

View file

@ -0,0 +1,186 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import "JoinNetworkViewController.h"
#import "ServiceCom.h"
#import "AppDelegate.h"
NSString * const JoinedNetworksKey = @"com.zerotier.one.joined-networks";
@interface NSString (extra)
- (BOOL)contains:(NSString*)find;
@end
@implementation NSString (extra)
- (BOOL)contains:(NSString*)find {
NSRange range = [self rangeOfString:find];
return range.location != NSNotFound;
}
@end
@implementation JoinNetworkViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do view setup here.
[self.network setDelegate:self];
[self.network setDataSource:self];
}
- (void)viewWillAppear {
[super viewWillAppear];
self.allowManagedCheckBox.state = NSOnState;
self.allowGlobalCheckBox.state = NSOffState;
self.allowDefaultCheckBox.state = NSOffState;
self.allowDNSCheckBox.state = NSOffState;
self.network.stringValue = @"";
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray<NSString*> *vals = [[defaults stringArrayForKey:JoinedNetworksKey] mutableCopy];
if(vals) {
self.values = vals;
}
}
- (void)viewWillDisappear {
[super viewWillDisappear];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:self.values forKey:JoinedNetworksKey];
}
- (IBAction)onJoinClicked:(id)sender {
NSString *networkId = self.network.stringValue;
NSError *error = nil;
[[ServiceCom sharedInstance] joinNetwork:networkId
allowManaged:(self.allowManagedCheckBox.state == NSOnState)
allowGlobal:(self.allowGlobalCheckBox.state == NSOnState)
allowDefault:(self.allowDefaultCheckBox.state == NSOnState)
allowDNS:(self.allowDNSCheckBox.state == NSOnState)
error:&error];
if(error) {
NSAlert *alert = [NSAlert alertWithError:error];
alert.alertStyle = NSCriticalAlertStyle;
[alert addButtonWithTitle:@"Ok"];
[alert runModal];
return;
}
self.network.stringValue = @"";
if(![self.values containsObject:networkId]) {
[self.values insertObject:networkId atIndex:0];
while([self.values count] > 20) {
[self.values removeLastObject];
}
}
[self.appDelegate closeJoinNetworkPopover];
}
// NSComboBoxDelegate methods
- (void)controlTextDidChange:(NSNotification *)obj {
NSComboBox *cb = (NSComboBox*)obj.object;
NSString *value = cb.stringValue;
NSString *allowedCharacters = @"abcdefABCDEF0123456789";
NSString *outValue = @"";
for(int i = 0; i < [value length]; ++i) {
if(![allowedCharacters contains:[NSString stringWithFormat:@"%C", [value characterAtIndex:i]]]) {
NSBeep();
}
else {
outValue = [outValue stringByAppendingString:[NSString stringWithFormat:@"%C", [value characterAtIndex:i]]];
}
}
if([outValue lengthOfBytesUsingEncoding:NSUTF8StringEncoding] == 16) {
self.joinButton.enabled = YES;
}
else {
if([outValue lengthOfBytesUsingEncoding:NSUTF8StringEncoding] > 16) {
NSRange range = {0, 16};
range = [outValue rangeOfComposedCharacterSequencesForRange:range];
outValue = [outValue substringWithRange:range];
NSBeep();
self.joinButton.enabled = YES;
}
else {
self.joinButton.enabled = NO;
}
}
cb.stringValue = outValue;
}
// end NSComboBoxDelegate methods
// NSComboBoxDataSource methods
- (NSInteger)numberOfItemsInComboBox:(NSComboBox *)aComboBox {
return [self.values count];
}
- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(NSInteger)index {
return [self.values objectAtIndex:index];
}
- (NSUInteger)comboBox:(NSComboBox *)aComboBox indexOfItemWithStringValue:(NSString *)string {
NSUInteger counter = 0;
for(NSString *val in self.values) {
if([val isEqualToString:string]) {
return counter;
}
counter += 1;
}
return NSNotFound;
}
- (NSString*)comboBox:(NSComboBox *)aComboBox completedString:(NSString *)string {
for(NSString *val in self.values) {
if([val hasPrefix:string]) {
return val;
}
}
return nil;
}
// end NSComboBoxDataSource methods
@end

View file

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="16097.3" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16097.3"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="JoinNetworkViewController" customModule="ZeroTier_One" customModuleProvider="target">
<connections>
<outlet property="allowDNSCheckBox" destination="LKY-vN-prS" id="COu-3z-092"/>
<outlet property="allowDefaultCheckBox" destination="rz3-0a-oNA" id="mYu-Wq-MHW"/>
<outlet property="allowGlobalCheckBox" destination="BH2-2O-Qeu" id="alx-Je-q9I"/>
<outlet property="allowManagedCheckBox" destination="OQS-QZ-zcY" id="7pz-vO-3IC"/>
<outlet property="joinButton" destination="BGy-vd-NQX" id="LGE-2G-7ND"/>
<outlet property="network" destination="BQy-d9-BNg" id="Yf7-BG-c84"/>
<outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView id="Hz6-mo-xeY">
<rect key="frame" x="0.0" y="0.0" width="397" height="106"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="puT-Yk-CWC">
<rect key="frame" x="18" y="66" width="107" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Enter Network ID" id="oYH-gS-BX5">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<comboBox verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="BQy-d9-BNg">
<rect key="frame" x="131" y="62" width="249" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<comboBoxCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" usesDataSource="YES" numberOfVisibleItems="5" id="n71-4S-AaI">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</comboBoxCell>
</comboBox>
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OQS-QZ-zcY">
<rect key="frame" x="18" y="42" width="115" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Allow Managed" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="QEN-MJ-xaj">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="BH2-2O-Qeu">
<rect key="frame" x="18" y="22" width="97" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Allow Global" bezelStyle="regularSquare" imagePosition="left" inset="2" id="epO-Uh-aHN">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="rz3-0a-oNA">
<rect key="frame" x="137" y="42" width="141" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Allow Default Route" bezelStyle="regularSquare" imagePosition="left" inset="2" id="Lkd-XI-Kcu">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LKY-vN-prS">
<rect key="frame" x="137" y="22" width="86" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Allow DNS" bezelStyle="regularSquare" imagePosition="left" inset="2" id="gGS-NZ-yu1">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="BGy-vd-NQX">
<rect key="frame" x="302" y="13" width="81" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Join" bezelStyle="rounded" alignment="center" enabled="NO" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="6Rp-TA-XLl">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="onJoinClicked:" target="-2" id="kzC-GT-JKb"/>
</connections>
</button>
</subviews>
<point key="canvasLocation" x="263.5" y="364"/>
</customView>
</objects>
</document>

View file

@ -0,0 +1,69 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Foundation/Foundation.h>
enum NetworkStatus {
REQUESTING_CONFIGURATION,
OK,
ACCESS_DENIED,
NOT_FOUND,
PORT_ERROR,
CLIENT_TOO_OLD,
};
enum NetworkType {
PUBLIC,
PRIVATE,
};
@interface Network : NSObject <NSCoding>
@property (readonly) NSArray<NSString*> *assignedAddresses;
@property (readonly) BOOL bridge;
@property (readonly) BOOL broadcastEnabled;
@property (readonly) BOOL dhcp;
@property (readonly) NSString *mac;
@property (readonly) int mtu;
@property (readonly) int netconfRevision;
@property (readonly) NSString *name;
@property (readonly) UInt64 nwid;
@property (readonly) NSString *portDeviceName;
@property (readonly) int portError;
@property (readonly) enum NetworkStatus status;
@property (readonly) enum NetworkType type;
@property (readonly) BOOL allowManaged;
@property (readonly) BOOL allowGlobal;
@property (readonly) BOOL allowDefault;
@property (readonly) BOOL allowDNS;
@property (readonly) BOOL connected; // not persisted. set to YES if loaded via json
- (id)initWithJsonData:(NSDictionary*)jsonData;
- (id)initWithCoder:(NSCoder *)aDecoder;
- (void)encodeWithCoder:(NSCoder *)aCoder;
+ (BOOL)defaultRouteExists:(NSArray<Network *>*)netList;
- (NSString*)statusString;
- (NSString*)typeString;
- (BOOL)hasSameNetworkId:(UInt64)networkId;
- (BOOL)isEqualToNetwork:(Network*)network;
- (BOOL)isEqual:(id)object;
- (NSUInteger)hash;
@end

View file

@ -0,0 +1,352 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import "Network.h"
NSString *NetworkAddressesKey = @"addresses";
NSString *NetworkBridgeKey = @"bridge";
NSString *NetworkBroadcastKey = @"broadcast";
NSString *NetworkDhcpKey = @"dhcp";
NSString *NetworkMacKey = @"mac";
NSString *NetworkMtuKey = @"mtu";
NSString *NetworkMulticastKey = @"multicast";
NSString *NetworkNameKey = @"name";
NSString *NetworkNetconfKey = @"netconf";
NSString *NetworkNwidKey = @"nwid";
NSString *NetworkPortNameKey = @"port";
NSString *NetworkPortErrorKey = @"portError";
NSString *NetworkStatusKey = @"status";
NSString *NetworkTypeKey = @"type";
NSString *NetworkAllowManagedKey = @"allowManaged";
NSString *NetworkAllowGlobalKey = @"allowGlobal";
NSString *NetworkAllowDefaultKey = @"allowDefault";
NSString *NetworkAllowDNSKey = @"allowDNS";
@implementation Network
- (id)initWithJsonData:(NSDictionary*)jsonData
{
self = [super init];
if(self) {
if([jsonData objectForKey:@"assignedAddresses"]) {
_assignedAddresses = (NSArray<NSString*>*)[jsonData objectForKey:@"assignedAddresses"];
}
if([jsonData objectForKey:@"bridge"]) {
_bridge = [(NSNumber*)[jsonData objectForKey:@"bridge"] boolValue];
}
if([jsonData objectForKey:@"broadcastEnabled"]) {
_broadcastEnabled = [(NSNumber*)[jsonData objectForKey:@"broadcastEnabled"] boolValue];
}
if([jsonData objectForKey:@"dhcp"]) {
_dhcp = [(NSNumber*)[jsonData objectForKey:@"dhcp"] boolValue];
}
if([jsonData objectForKey:@"mac"]) {
_mac = (NSString*)[jsonData objectForKey:@"mac"];
}
if([jsonData objectForKey:@"mtu"]) {
_mtu = [(NSNumber*)[jsonData objectForKey:@"mtu"] intValue];
}
if([jsonData objectForKey:@"name"]) {
_name = (NSString*)[jsonData objectForKey:@"name"];
}
if([jsonData objectForKey:@"netconfRevision"]) {
_netconfRevision = [(NSNumber*)[jsonData objectForKey:@"netconfRevision"] intValue];
}
if([jsonData objectForKey:@"nwid"]) {
NSString *networkid = (NSString*)[jsonData objectForKey:@"nwid"];
NSScanner *scanner = [NSScanner scannerWithString:networkid];
[scanner scanHexLongLong:&_nwid];
}
if([jsonData objectForKey:@"portDeviceName"]) {
_portDeviceName = (NSString*)[jsonData objectForKey:@"portDeviceName"];
}
if([jsonData objectForKey:@"portError"]) {
_portError = [(NSNumber*)[jsonData objectForKey:@"portError"] intValue];
}
if([jsonData objectForKey:@"allowManaged"]) {
_allowManaged = [(NSNumber*)[jsonData objectForKey:@"allowManaged"] boolValue];
}
if([jsonData objectForKey:@"allowGlobal"]) {
_allowGlobal = [(NSNumber*)[jsonData objectForKey:@"allowGlobal"] boolValue];
}
if([jsonData objectForKey:@"allowDefault"]) {
_allowDefault = [(NSNumber*)[jsonData objectForKey:@"allowDefault"] boolValue];
}
if([jsonData objectForKey:@"allowDNS"]) {
_allowDNS = [(NSNumber*)[jsonData objectForKey:@"allowDNS"] boolValue];
} else {
_allowDNS = false;
}
if([jsonData objectForKey:@"status"]) {
NSString *statusStr = (NSString*)[jsonData objectForKey:@"status"];
if([statusStr isEqualToString:@"REQUESTING_CONFIGURATION"]) {
_status = REQUESTING_CONFIGURATION;
}
else if([statusStr isEqualToString:@"OK"]) {
_status = OK;
}
else if([statusStr isEqualToString:@"ACCESS_DENIED"]) {
_status = ACCESS_DENIED;
}
else if([statusStr isEqualToString:@"NOT_FOUND"]) {
_status = NOT_FOUND;
}
else if([statusStr isEqualToString:@"PORT_ERROR"]) {
_status = PORT_ERROR;
}
else if([statusStr isEqualToString:@"CLIENT_TOO_OLD"]) {
_status = CLIENT_TOO_OLD;
}
}
if([jsonData objectForKey:@"type"]) {
NSString *typeStr = (NSString*)[jsonData objectForKey:@"type"];
if([typeStr isEqualToString:@"PRIVATE"]) {
_type = PRIVATE;
}
else if([typeStr isEqualToString:@"PUBLIC"]) {
_type = PUBLIC;
}
}
_connected = YES;
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if(self) {
if([aDecoder containsValueForKey:NetworkAddressesKey]) {
_assignedAddresses = (NSArray<NSString*>*)[aDecoder decodeObjectForKey:NetworkAddressesKey];
}
if([aDecoder containsValueForKey:NetworkBridgeKey]) {
_bridge = [aDecoder decodeBoolForKey:NetworkBridgeKey];
}
if([aDecoder containsValueForKey:NetworkBroadcastKey]) {
_broadcastEnabled = [aDecoder decodeBoolForKey:NetworkBroadcastKey];
}
if([aDecoder containsValueForKey:NetworkDhcpKey]) {
_dhcp = [aDecoder decodeBoolForKey:NetworkDhcpKey];
}
if([aDecoder containsValueForKey:NetworkMacKey]) {
_mac = (NSString*)[aDecoder decodeObjectForKey:NetworkMacKey];
}
if([aDecoder containsValueForKey:NetworkMtuKey]) {
_mtu = (int)[aDecoder decodeIntegerForKey:NetworkMtuKey];
}
if([aDecoder containsValueForKey:NetworkNameKey]) {
_name = (NSString*)[aDecoder decodeObjectForKey:NetworkNameKey];
}
if([aDecoder containsValueForKey:NetworkNetconfKey]) {
_netconfRevision = (int)[aDecoder decodeIntegerForKey:NetworkNetconfKey];
}
if([aDecoder containsValueForKey:NetworkNwidKey]) {
_nwid = [(NSNumber*)[aDecoder decodeObjectForKey:NetworkNwidKey] unsignedLongLongValue];
}
if([aDecoder containsValueForKey:NetworkPortNameKey]) {
_portDeviceName = (NSString*)[aDecoder decodeObjectForKey:NetworkPortNameKey];
}
if([aDecoder containsValueForKey:NetworkPortErrorKey]) {
_portError = (int)[aDecoder decodeIntegerForKey:NetworkPortErrorKey];
}
if([aDecoder containsValueForKey:NetworkStatusKey]) {
_status = (enum NetworkStatus)[aDecoder decodeIntegerForKey:NetworkStatusKey];
}
if([aDecoder containsValueForKey:NetworkTypeKey]) {
_type = (enum NetworkType)[aDecoder decodeIntegerForKey:NetworkTypeKey];
}
if([aDecoder containsValueForKey:NetworkAllowManagedKey]) {
_allowManaged = [aDecoder decodeBoolForKey:NetworkAllowManagedKey];
}
if([aDecoder containsValueForKey:NetworkAllowGlobalKey]) {
_allowGlobal = [aDecoder decodeBoolForKey:NetworkAllowGlobalKey];
}
if([aDecoder containsValueForKey:NetworkAllowDefaultKey]) {
_allowDefault = [aDecoder decodeBoolForKey:NetworkAllowDefaultKey];
}
if([aDecoder containsValueForKey:NetworkAllowDNSKey]) {
_allowDNS = [aDecoder decodeBoolForKey:NetworkAllowDNSKey];
} else {
_allowDNS = false;
}
_connected = NO;
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:_assignedAddresses forKey:NetworkAddressesKey];
[aCoder encodeBool:_bridge forKey:NetworkBridgeKey];
[aCoder encodeBool:_broadcastEnabled forKey:NetworkBroadcastKey];
[aCoder encodeBool:_dhcp forKey:NetworkDhcpKey];
[aCoder encodeObject:_mac forKey:NetworkMacKey];
[aCoder encodeInteger:_mtu forKey:NetworkMtuKey];
[aCoder encodeObject:_name forKey:NetworkNameKey];
[aCoder encodeInteger:_netconfRevision forKey:NetworkNetconfKey];
[aCoder encodeObject:[NSNumber numberWithUnsignedLongLong:_nwid]
forKey:NetworkNwidKey];
[aCoder encodeObject:_portDeviceName forKey:NetworkPortNameKey];
[aCoder encodeInteger:_portError forKey:NetworkPortErrorKey];
[aCoder encodeInteger:_status forKey:NetworkStatusKey];
[aCoder encodeInteger:_type forKey:NetworkTypeKey];
[aCoder encodeBool:_allowManaged forKey:NetworkAllowManagedKey];
[aCoder encodeBool:_allowGlobal forKey:NetworkAllowGlobalKey];
[aCoder encodeBool:_allowDefault forKey:NetworkAllowDefaultKey];
[aCoder encodeBool:_allowDNS forKey:NetworkAllowDNSKey];
}
+ (BOOL)defaultRouteExists:(NSArray<Network *>*)netList
{
for(Network *net in netList) {
if (net.allowDefault && net.connected) {
return YES;
}
}
return NO;
}
- (NSString*)statusString {
switch(_status) {
case REQUESTING_CONFIGURATION:
return @"REQUESTING_CONFIGURATION";
case OK:
return @"OK";
case ACCESS_DENIED:
return @"ACCESS_DENIED";
case NOT_FOUND:
return @"NOT_FOUND";
case PORT_ERROR:
return @"PORT_ERROR";
case CLIENT_TOO_OLD:
return @"CLIENT_TOO_OLD";
default:
return @"";
}
}
- (NSString*)typeString {
switch(_type) {
case PUBLIC:
return @"PUBLIC";
case PRIVATE:
return @"PRIVATE";
default:
return @"";
}
}
- (BOOL)hasSameNetworkId:(UInt64)networkId
{
return self.nwid == networkId;
}
- (BOOL)isEqualToNetwork:(Network*)network
{
return [self.assignedAddresses isEqualToArray:network.assignedAddresses] &&
self.bridge == network.bridge &&
self.broadcastEnabled == network.broadcastEnabled &&
self.dhcp == network.dhcp &&
[self.mac isEqualToString:network.mac] &&
self.mtu == network.mtu &&
self.netconfRevision == network.netconfRevision &&
[self.name isEqualToString:network.name] &&
self.nwid == network.nwid &&
[self.portDeviceName isEqualToString:network.portDeviceName] &&
self.status == network.status &&
self.type == network.type &&
self.allowManaged == network.allowManaged &&
self.allowGlobal == network.allowGlobal &&
self.allowDefault == network.allowDefault &&
self.allowDNS == network.allowDNS &&
self.connected == network.connected;
}
- (BOOL)isEqual:(id)object
{
if (self == object) {
return YES;
}
if (![object isKindOfClass:[Network class]]) {
return NO;
}
return [self isEqualToNetwork:object];
}
- (NSUInteger)hash
{
return [self.assignedAddresses hash] ^
self.bridge ^
self.broadcastEnabled ^
self.dhcp ^
[self.mac hash] ^
self.mtu ^
self.netconfRevision ^
[self.name hash] ^
self.nwid ^
[self.portDeviceName hash] ^
self.portError ^
self.status ^
self.type ^
self.allowManaged ^
self.allowGlobal ^
self.allowDefault ^
self.allowDNS ^
self.connected;
}
@end

View file

@ -0,0 +1,51 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
@class ShowNetworksViewController;
@interface NetworkInfoCell : NSTableCellView
@property (weak, nonatomic) ShowNetworksViewController *parent;
@property (weak, nonatomic) IBOutlet NSTextField *networkIdField;
@property (weak, nonatomic) IBOutlet NSTextField *networkNameField;
@property (weak, nonatomic) IBOutlet NSTextField *statusField;
@property (weak, nonatomic) IBOutlet NSTextField *typeField;
@property (weak, nonatomic) IBOutlet NSTextField *macField;
@property (weak, nonatomic) IBOutlet NSTextField *mtuField;
@property (weak, nonatomic) IBOutlet NSTextField *broadcastField;
@property (weak, nonatomic) IBOutlet NSTextField *bridgingField;
@property (weak, nonatomic) IBOutlet NSTextField *deviceField;
@property (weak, nonatomic) IBOutlet NSTextField *addressesField;
@property (weak, nonatomic) IBOutlet NSButton *allowManaged;
@property (weak, nonatomic) IBOutlet NSButton *allowGlobal;
@property (weak, nonatomic) IBOutlet NSButton *allowDefault;
@property (weak, nonatomic) IBOutlet NSButton *allowDNS;
@property (weak, nonatomic) IBOutlet NSButton *connectedCheckbox;
@property (weak, nonatomic) IBOutlet NSButton *deleteButton;
- (IBAction)onConnectCheckStateChanged:(NSButton*)sender;
- (IBAction)deleteNetwork:(NSButton*)sender;
- (IBAction)onAllowStatusChanged:(NSButton*)sender;
- (void)joinNetwork:(NSString*)nwid;
- (void)leaveNetwork:(NSString*)nwid;
@end

View file

@ -0,0 +1,86 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import "NetworkInfoCell.h"
#import "ServiceCom.h"
#import "ShowNetworksViewController.h"
#import "Network.h"
@implementation NetworkInfoCell
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
// Drawing code here.
}
- (IBAction)onConnectCheckStateChanged:(NSButton*)sender
{
if(sender.state == NSOnState) {
[self joinNetwork:self.networkIdField.stringValue];
}
else {
[self leaveNetwork:self.networkIdField.stringValue];
}
}
- (IBAction)deleteNetwork:(NSButton*)sender;
{
[self leaveNetwork:self.networkIdField.stringValue];
[self.parent deleteNetworkFromList:self.networkIdField.stringValue];
}
- (IBAction)onAllowStatusChanged:(NSButton*)sender
{
[self joinNetwork:self.networkIdField.stringValue];
}
- (void)joinNetwork:(NSString*)nwid
{
NSError *error = nil;
[[ServiceCom sharedInstance] joinNetwork:nwid
allowManaged:(self.allowManaged.state == NSOnState)
allowGlobal:(self.allowGlobal.state == NSOnState)
allowDefault:![Network defaultRouteExists:_parent.networkList] && (self.allowDefault.state == NSOnState)
allowDNS:(self.allowDNS.state == NSOnState)
error:&error];
if (error) {
NSAlert *alert = [NSAlert alertWithError:error];
alert.alertStyle = NSCriticalAlertStyle;
[alert addButtonWithTitle:@"Ok"];
[alert runModal];
}
}
- (void)leaveNetwork:(NSString*)nwid
{
NSError *error = nil;
[[ServiceCom sharedInstance] leaveNetwork:nwid error:&error];
if (error) {
NSAlert *alert = [NSAlert alertWithError:error];
alert.alertStyle = NSCriticalAlertStyle;
[alert addButtonWithTitle:@"Ok"];
[alert runModal];
}
}
@end

View file

@ -0,0 +1,45 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Foundation/Foundation.h>
extern NSString * const NetworkUpdateKey;
extern NSString * const StatusUpdateKey;
@class Network;
@interface NetworkMonitor : NSObject
{
NSMutableArray<Network*> *_savedNetworks;
NSArray<Network*> *_receivedNetworks;
NSMutableArray<Network*> *_allNetworks;
NSTimer *_timer;
}
- (id)init;
- (void)dealloc;
- (void)start;
- (void)stop;
- (void)updateNetworkInfo;
- (void)deleteSavedNetwork:(NSString*)networkId;
@end

View file

@ -0,0 +1,253 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import "NetworkMonitor.h"
#import "Network.h"
#import "ServiceCom.h"
#import "NodeStatus.h"
@import AppKit;
NSString * const NetworkUpdateKey = @"com.zerotier.one.network-list";
NSString * const StatusUpdateKey = @"com.zerotier.one.status";
@interface NetworkMonitor (private)
- (NSString*)dataFile;
- (void)internal_updateNetworkInfo;
- (NSInteger)findNetworkWithID:(UInt64)networkId;
- (NSInteger)findSavedNetworkWithID:(UInt64)networkId;
- (void)saveNetworks;
@end
@implementation NetworkMonitor
- (id)init
{
self = [super init];
if(self)
{
_savedNetworks = [NSMutableArray<Network*> array];
_receivedNetworks = [NSArray<Network*> array];
_allNetworks = [NSMutableArray<Network*> array];
_timer = nil;
}
return self;
}
- (void)dealloc
{
[_timer invalidate];
}
- (void)start
{
NSLog(@"ZeroTier monitor started");
_timer = [NSTimer scheduledTimerWithTimeInterval:1.0f
target:self
selector:@selector(updateNetworkInfo)
userInfo:nil
repeats:YES];
}
- (void)stop
{
NSLog(@"ZeroTier monitor stopped");
[_timer invalidate];
_timer = nil;
}
- (void)updateNetworkInfo
{
NSString *filePath = [self dataFile];
if([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
NSArray<Network*> *networks = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
if(networks != nil) {
_savedNetworks = [networks mutableCopy];
}
}
NSError *error = nil;
[[ServiceCom sharedInstance] getNetworklist:^(NSArray<Network *> *networkList) {
_receivedNetworks = networkList;
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self internal_updateNetworkInfo];
} ];
} error:&error];
if(error) {
[self stop];
NSAlert *alert = [NSAlert alertWithError:error];
alert.alertStyle = NSCriticalAlertStyle;
[alert addButtonWithTitle:@"Quit"];
[alert addButtonWithTitle:@"Retry"];
NSModalResponse res = [alert runModal];
if(res == NSAlertFirstButtonReturn) {
[NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
}
else if(res == NSAlertSecondButtonReturn) {
[self start];
return;
}
}
[[ServiceCom sharedInstance] getNodeStatus:^(NodeStatus *status) {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:status forKey:@"status"];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[[NSNotificationCenter defaultCenter] postNotificationName:StatusUpdateKey
object:nil
userInfo:userInfo];
}];
} error:&error];
if (error) {
[self stop];
NSAlert *alert = [NSAlert alertWithError:error];
alert.alertStyle = NSCriticalAlertStyle;
[alert addButtonWithTitle:@"Quit"];
[alert addButtonWithTitle:@"Retry"];
NSModalResponse res = [alert runModal];
if(res == NSAlertFirstButtonReturn) {
[NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
}
else if(res == NSAlertSecondButtonReturn) {
[self start];
return;
}
}
}
- (void)deleteSavedNetwork:(NSString*)networkId
{
UInt64 nwid = 0;
NSScanner *scanner = [NSScanner scannerWithString:networkId];
[scanner scanHexLongLong:&nwid];
NSInteger index = [self findNetworkWithID:nwid];
if(index != NSNotFound) {
[_allNetworks removeObjectAtIndex:index];
}
index = [self findSavedNetworkWithID:nwid];
if(index != NSNotFound) {
[_savedNetworks removeObjectAtIndex:index];
}
[self saveNetworks];
}
@end
@implementation NetworkMonitor (private)
- (NSString*)dataFile
{
NSURL *appSupport = [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory
inDomains:NSUserDomainMask] objectAtIndex:0];
appSupport = [[[appSupport URLByAppendingPathComponent:@"ZeroTier"] URLByAppendingPathComponent:@"One"] URLByAppendingPathComponent:@"networkinfo.dat"];
return appSupport.path;
}
- (void)internal_updateNetworkInfo
{
NSMutableArray<Network*> *networks = [_savedNetworks mutableCopy];
for(Network *nw in _receivedNetworks) {
NSInteger index = [self findSavedNetworkWithID:nw.nwid];
if(index != NSNotFound) {
[networks setObject:nw atIndexedSubscript:index];
}
else {
[networks addObject:nw];
}
}
[networks sortUsingComparator:^NSComparisonResult(Network *obj1, Network *obj2) {
if(obj1.nwid > obj2.nwid) {
return true;
}
return false;
}];
@synchronized(_allNetworks) {
_allNetworks = networks;
}
[self saveNetworks];
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:networks forKey:@"networks"];
[[NSNotificationCenter defaultCenter] postNotificationName:NetworkUpdateKey
object:nil
userInfo:userInfo];
}
- (NSInteger)findNetworkWithID:(UInt64)networkId
{
for(int i = 0; i < [_allNetworks count]; ++i) {
Network *nw = [_allNetworks objectAtIndex:i];
if(nw.nwid == networkId) {
return i;
}
}
return NSNotFound;
}
- (NSInteger)findSavedNetworkWithID:(UInt64)networkId
{
for(int i = 0; i < [_savedNetworks count]; ++i) {
Network *nw = [_savedNetworks objectAtIndex:i];
if(nw.nwid == networkId) {
return i;
}
}
return NSNotFound;
}
- (void)saveNetworks
{
NSString *filePath = [self dataFile];
@synchronized(_allNetworks) {
[NSKeyedArchiver archiveRootObject:_allNetworks toFile:filePath];
}
}
@end

View file

@ -0,0 +1,35 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Foundation/Foundation.h>
@interface NodeStatus : NSObject
@property (readonly) NSString *address;
@property (readonly) NSString *publicIdentity;
@property (readonly) BOOL online;
@property (readonly) BOOL tcpFallbackActive;
@property (readonly) int versionMajor;
@property (readonly) int versionMinor;
@property (readonly) int versionRev;
@property (readonly) NSString *version;
@property (readonly) UInt64 clock;
- (id)initWithJsonData:(NSDictionary*)jsonData;
@end

View file

@ -0,0 +1,40 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import "NodeStatus.h"
@implementation NodeStatus
- (id)initWithJsonData:(NSDictionary*)jsonData
{
self = [super init];
if(self) {
_address = (NSString*)[jsonData objectForKey:@"address"];
_publicIdentity = (NSString*)[jsonData objectForKey:@"publicIdentity"];
_online = [(NSNumber*)[jsonData objectForKey:@"online"] boolValue];
_tcpFallbackActive = [(NSNumber*)[jsonData objectForKey:@"tcpFallbackActive"] boolValue];
_versionMajor = [(NSNumber*)[jsonData objectForKey:@"versionMajor"] intValue];
_versionMinor = [(NSNumber*)[jsonData objectForKey:@"versionMinor"] intValue];
_versionRev = [(NSNumber*)[jsonData objectForKey:@"versionRev"] intValue];
_version = (NSString*)[jsonData objectForKey:@"version"];
_clock = [(NSNumber*)[jsonData objectForKey:@"clock"] unsignedLongLongValue];
}
return self;
}
@end

View file

@ -0,0 +1,31 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
@interface PreferencesViewController : NSViewController
@property (nonatomic, weak) IBOutlet NSButton *startupCheckBox;
- (IBAction)onStartupCheckBoxChanged:(NSButton*)sender;
- (BOOL)isLaunchAtStartup;
- (LSSharedFileListItemRef)itemRefInLoginItems;
- (void)setLaunchAtLoginEnabled:(BOOL)enabled;
@end

View file

@ -0,0 +1,112 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import "PreferencesViewController.h"
@interface PreferencesViewController ()
@end
@implementation PreferencesViewController
- (void)viewDidLoad {
[super viewDidLoad];
if([self isLaunchAtStartup]) {
self.startupCheckBox.state = NSOnState;
}
else {
self.startupCheckBox.state = NSOffState;
}
}
- (IBAction)onStartupCheckBoxChanged:(NSButton *)sender
{
if(sender.state == NSOnState) {
[self setLaunchAtLoginEnabled:YES];
}
else {
[self setLaunchAtLoginEnabled:NO];
}
}
- (void)setLaunchAtLoginEnabled:(BOOL)enabled
{
LSSharedFileListRef loginItemsRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
if (enabled) {
// Add the app to the LoginItems list.
CFURLRef appUrl = (__bridge CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
LSSharedFileListItemRef itemRef = LSSharedFileListInsertItemURL(loginItemsRef, kLSSharedFileListItemLast, NULL, NULL, appUrl, NULL, NULL);
if (itemRef) CFRelease(itemRef);
}
else {
// Remove the app from the LoginItems list.
LSSharedFileListItemRef itemRef = [self itemRefInLoginItems];
LSSharedFileListItemRemove(loginItemsRef,itemRef);
if (itemRef != nil) CFRelease(itemRef);
}
}
- (BOOL)isLaunchAtStartup {
// See if the app is currently in LoginItems.
LSSharedFileListItemRef itemRef = [self itemRefInLoginItems];
// Store away that boolean.
BOOL isInList = itemRef != nil;
// Release the reference if it exists.
if (itemRef != nil) CFRelease(itemRef);
return isInList;
}
- (LSSharedFileListItemRef)itemRefInLoginItems {
LSSharedFileListItemRef itemRef = nil;
NSString * appPath = [[NSBundle mainBundle] bundlePath];
// This will retrieve the path for the application
// For example, /Applications/test.app
CFURLRef url = (__bridge CFURLRef)[NSURL fileURLWithPath:appPath];
// Create a reference to the shared file list.
LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
if (loginItems) {
UInt32 seedValue;
//Retrieve the list of Login Items and cast them to
// a NSArray so that it will be easier to iterate.
NSArray *loginItemsArray = (__bridge NSArray *)LSSharedFileListCopySnapshot(loginItems, &seedValue);
for(int i = 0; i< [loginItemsArray count]; i++){
LSSharedFileListItemRef currentItemRef = (__bridge LSSharedFileListItemRef)[loginItemsArray
objectAtIndex:i];
//Resolve the item with URL
if (LSSharedFileListItemResolve(currentItemRef, 0, (CFURLRef*) &url, NULL) == noErr) {
NSString * urlPath = [(__bridge NSURL*)url path];
if ([urlPath compare:appPath] == NSOrderedSame){
itemRef = currentItemRef;
}
}
}
}
CFRelease(loginItems);
return itemRef;
}
@end

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10116" systemVersion="15F34" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10116"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="PreferencesViewController" customModule="ZeroTier_One" customModuleProvider="target">
<connections>
<outlet property="startupCheckBox" destination="XSk-jN-ner" id="nvL-b1-gza"/>
<outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView id="Hz6-mo-xeY">
<rect key="frame" x="0.0" y="0.0" width="284" height="54"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="XSk-jN-ner">
<rect key="frame" x="18" y="18" width="248" height="18"/>
<buttonCell key="cell" type="check" title="Start ZeroTier One on system startup" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="VkJ-h4-tHf">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="onStartupCheckBoxChanged:" target="-2" id="zAQ-DJ-c3w"/>
</connections>
</button>
</subviews>
<point key="canvasLocation" x="365" y="208"/>
</customView>
</objects>
</document>

View file

@ -0,0 +1,40 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Foundation/Foundation.h>
@class NodeStatus;
@class Network;
@interface ServiceCom : NSObject
{
NSString *baseURL;
NSURLSession *session;
BOOL _isQuitting;
BOOL _resetKey;
}
+ (ServiceCom*)sharedInstance;
- (id)init;
- (void)getNetworklist:(void (^)(NSArray<Network*>*))completionHandler error:(NSError* __autoreleasing *)error;
- (void)getNodeStatus:(void (^)(NodeStatus*))completionHandler error:(NSError*__autoreleasing*)error;
- (void)joinNetwork:(NSString*)networkId allowManaged:(BOOL)allowManaged allowGlobal:(BOOL)allowGlobal allowDefault:(BOOL)allowDefault allowDNS:(BOOL)allowDNS error:(NSError*__autoreleasing*)error;
- (void)leaveNetwork:(NSString*)networkId error:(NSError*__autoreleasing*)error;
@end

View file

@ -0,0 +1,522 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import "ServiceCom.h"
#import "AuthtokenCopy.h"
#import "Network.h"
#import "NodeStatus.h"
@import AppKit;
@interface ServiceCom (Private)
- (NSString*)key;
@end
@implementation ServiceCom
+ (ServiceCom*)sharedInstance {
static ServiceCom *sc = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sc = [[ServiceCom alloc] init];
});
return sc;
}
- (id)init
{
self = [super init];
if(self) {
baseURL = @"http://127.0.0.1:9993";
session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration]];
_isQuitting = NO;
_resetKey = NO;
}
return self;
}
- (NSString*)key:(NSError* __autoreleasing *)err
{
static NSString *k = nil;
static NSUInteger resetCount = 0;
@synchronized (self) {
if (_isQuitting) {
return @"";
}
if (_resetKey && k != nil) {
k = nil;
++resetCount;
NSLog(@"ResetCount: %lu", (unsigned long)resetCount);
if (resetCount > 10) {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSAlert *alert = [NSAlert alertWithMessageText:@"Error obtaining Auth Token"
defaultButton:@"Quit"
alternateButton:@"Retry"
otherButton:nil
informativeTextWithFormat:@"Please ensure ZeroTier is installed correctly"];
alert.alertStyle = NSCriticalAlertStyle;
NSModalResponse res;
if (!_isQuitting) {
res = [alert runModal];
}
else {
return;
}
if(res == 1) {
_isQuitting = YES;
[NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
}
}];
return @"";
}
}
if (k == nil) {
NSError *error = nil;
NSURL *appSupportDir = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:false error:&error];
if (error) {
NSLog(@"Error: %@", error);
return @"";
}
appSupportDir = [[appSupportDir URLByAppendingPathComponent:@"ZeroTier"] URLByAppendingPathComponent:@"One"];
NSURL *authtokenURL = [appSupportDir URLByAppendingPathComponent:@"authtoken.secret"];
if (!_resetKey && [[NSFileManager defaultManager] fileExistsAtPath:[authtokenURL path]]) {
k = [NSString stringWithContentsOfURL:authtokenURL
encoding:NSUTF8StringEncoding
error:&error];
k = [k stringByReplacingOccurrencesOfString:@"\n" withString:@""];
if (error) {
NSLog(@"Error: %@", error);
k = nil;
*err = error;
return @"";
}
}
else {
_resetKey = NO;
NSURL *sysAppSupportDir = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory inDomain:NSSystemDomainMask appropriateForURL:nil create:false error:nil];
sysAppSupportDir = [[sysAppSupportDir URLByAppendingPathComponent:@"ZeroTier"] URLByAppendingPathComponent:@"One"];
NSURL *sysAuthtokenURL = [sysAppSupportDir URLByAppendingPathComponent:@"authtoken.secret"];
if(![[NSFileManager defaultManager] fileExistsAtPath:[sysAuthtokenURL path]]) {
}
[[NSFileManager defaultManager] createDirectoryAtURL:appSupportDir
withIntermediateDirectories:YES
attributes:nil
error:&error];
if (error) {
NSLog(@"Error: %@", error);
*err = error;
k = nil;
return @"";
}
AuthorizationRef authRef;
OSStatus status = AuthorizationCreate(nil, nil, kAuthorizationFlagDefaults, &authRef);
if (status != errAuthorizationSuccess) {
NSLog(@"Authorization Failed! %d", status);
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't create AuthorizationRef", nil),
};
*err = [NSError errorWithDomain:@"com.zerotier.one" code:-1 userInfo:userInfo];
return @"";
}
AuthorizationItem authItem;
authItem.name = kAuthorizationRightExecute;
authItem.valueLength = 0;
authItem.flags = 0;
AuthorizationRights authRights;
authRights.count = 1;
authRights.items = &authItem;
AuthorizationFlags authFlags = kAuthorizationFlagDefaults |
kAuthorizationFlagInteractionAllowed |
kAuthorizationFlagPreAuthorize |
kAuthorizationFlagExtendRights;
status = AuthorizationCopyRights(authRef, &authRights, nil, authFlags, nil);
if (status != errAuthorizationSuccess) {
NSLog(@"Authorization Failed! %d", status);
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't copy authorization rights", nil),
};
*err = [NSError errorWithDomain:@"com.zerotier.one" code:-1 userInfo:userInfo];
return @"";
}
NSString *localKey = getAdminAuthToken(authRef);
AuthorizationFree(authRef, kAuthorizationFlagDestroyRights);
if (localKey != nil && [localKey lengthOfBytesUsingEncoding:NSUTF8StringEncoding] > 0) {
k = localKey;
[localKey writeToURL:authtokenURL
atomically:YES
encoding:NSUTF8StringEncoding
error:&error];
if (error) {
NSLog(@"Error writing token to disk: %@", error);
*err = error;
}
}
}
}
if (k == nil) {
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: NSLocalizedString(@"Unknown error finding authorization key", nil),
};
*err = [NSError errorWithDomain:@"com.zerotier.one" code:-1 userInfo:userInfo];
return @"";
}
}
return k;
}
- (void)getNetworklist:(void (^)(NSArray<Network *> *))completionHandler error:(NSError *__autoreleasing*)error
{
NSString* key = [self key:error];
if(*error) {
return;
}
NSString *urlString = [[baseURL stringByAppendingString:@"/network?auth="] stringByAppendingString:key];
NSURL *url = [NSURL URLWithString:urlString];
NSURLSessionDataTask *task =
[session dataTaskWithURL:url
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable err) {
if (err) {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSAlert *alert = [NSAlert alertWithError:err];
alert.alertStyle = NSCriticalAlertStyle;
[alert addButtonWithTitle:@"Quit"];
[alert addButtonWithTitle:@"Retry"];
NSModalResponse res;
if (!_isQuitting) {
res = [alert runModal];
}
else {
return;
}
if(res == NSAlertFirstButtonReturn) {
[NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
_isQuitting = YES;
}
}];
return;
}
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
NSInteger status = [httpResponse statusCode];
NSError *err2;
if (status == 200) {
NSArray *json = [NSJSONSerialization JSONObjectWithData:data
options:0
error:&err2];
if (err) {
NSLog(@"Error fetching network list: %@", err2);
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSAlert *alert = [NSAlert alertWithError:err2];
alert.alertStyle = NSCriticalAlertStyle;
[alert addButtonWithTitle:@"Quit"];
[alert addButtonWithTitle:@"Retry"];
NSModalResponse res;
if (!_isQuitting) {
res = [alert runModal];
}
else {
return;
}
if(res == NSAlertFirstButtonReturn) {
_isQuitting = YES;
[NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
}
}];
return;
}
NSMutableArray<Network*> *networks = [[NSMutableArray<Network*> alloc] init];
for(NSDictionary *dict in json) {
[networks addObject:[[Network alloc] initWithJsonData:dict]];
}
completionHandler(networks);
}
else if (status == 401) {
self->_resetKey = YES;
}
}];
[task resume];
}
- (void)getNodeStatus:(void (^)(NodeStatus*))completionHandler error:(NSError*__autoreleasing*)error
{
NSString *key = [self key:error];
if(*error) {
return;
}
NSString *urlString = [[baseURL stringByAppendingString:@"/status?auth="] stringByAppendingString:key];
NSURL *url = [NSURL URLWithString:urlString];
NSURLSessionDataTask *task =
[session dataTaskWithURL:url
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable err) {
if(err) {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSAlert *alert = [NSAlert alertWithError:err];
alert.alertStyle = NSCriticalAlertStyle;
[alert addButtonWithTitle:@"Quit"];
[alert addButtonWithTitle:@"Retry"];
NSModalResponse res;
if (!_isQuitting) {
res = [alert runModal];
}
else {
return;
}
if(res == NSAlertFirstButtonReturn) {
[NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
_isQuitting = YES;
}
}];
return;
}
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
NSInteger status = [httpResponse statusCode];
NSError *err2;
if(status == 200) {
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data
options:0
error:&err2];
if(err2) {
NSLog(@"Error fetching node status: %@", err2);
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSAlert *alert = [NSAlert alertWithError:err2];
alert.alertStyle = NSCriticalAlertStyle;
[alert addButtonWithTitle:@"Quit"];
[alert addButtonWithTitle:@"Retry"];
NSModalResponse res;
if (!_isQuitting) {
res = [alert runModal];
}
else {
return;
}
if(res == NSAlertFirstButtonReturn) {
[NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
_isQuitting = YES;
}
}];
return;
}
NodeStatus *status = [[NodeStatus alloc] initWithJsonData:json];
completionHandler(status);
}
else if (status == 401) {
self->_resetKey = YES;
}
}];
[task resume];
}
- (void)joinNetwork:(NSString*)networkId
allowManaged:(BOOL)allowManaged
allowGlobal:(BOOL)allowGlobal
allowDefault:(BOOL)allowDefault
allowDNS:(BOOL)allowDNS
error:(NSError *__autoreleasing*)error
{
NSString *key = [self key:error];
if(*error) {
return;
}
NSString *urlString = [[[[baseURL stringByAppendingString:@"/network/"]
stringByAppendingString:networkId]
stringByAppendingString:@"?auth="]
stringByAppendingString:key];
NSURL *url = [NSURL URLWithString:urlString];
NSMutableDictionary *jsonDict = [NSMutableDictionary dictionary];
[jsonDict setObject:[NSNumber numberWithBool:allowManaged] forKey:@"allowManaged"];
[jsonDict setObject:[NSNumber numberWithBool:allowGlobal] forKey:@"allowGlobal"];
[jsonDict setObject:[NSNumber numberWithBool:allowDefault] forKey:@"allowDefault"];
[jsonDict setObject:[NSNumber numberWithBool:allowDNS] forKey:@"allowDNS"];
NSError *err = nil;
NSData *json = [NSJSONSerialization dataWithJSONObject:jsonDict
options:0
error:&err];
if(err) {
NSLog(@"Error creating json data: %@", err);
*error = err;
return;
}
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
request.HTTPBody = json;
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
NSURLSessionDataTask *task =
[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable err) {
if(err) {
NSLog(@"Error posting join request: %@", err);
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSAlert *alert = [NSAlert alertWithError:err];
alert.alertStyle = NSCriticalAlertStyle;
[alert addButtonWithTitle:@"Quit"];
[alert addButtonWithTitle:@"Retry"];
NSModalResponse res;
if (!_isQuitting) {
res = [alert runModal];
}
else {
return;
}
if(res == NSAlertFirstButtonReturn) {
[NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
_isQuitting = YES;
}
}];
}
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
NSInteger status = [httpResponse statusCode];
if(status == 200) {
NSLog(@"join ok");
}
else if (status == 401) {
self->_resetKey = YES;
}
else {
NSLog(@"join error: %ld", (long)status);
}
}];
[task resume];
}
- (void)leaveNetwork:(NSString*)networkId error:(NSError*__autoreleasing*)error
{
NSString *key = [self key:error];
if(*error) {
return;
}
NSString *urlString = [[[[baseURL stringByAppendingString:@"/network/"]
stringByAppendingString:networkId]
stringByAppendingString:@"?auth="]
stringByAppendingString:key];
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"DELETE";
NSURLSessionDataTask *task =
[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable err) {
if(err) {
NSLog(@"Error posting delete request: %@", err);
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSAlert *alert = [NSAlert alertWithError:err];
alert.alertStyle = NSCriticalAlertStyle;
[alert addButtonWithTitle:@"Quit"];
[alert addButtonWithTitle:@"Retry"];
NSModalResponse res;
if (!_isQuitting) {
res = [alert runModal];
}
else {
return;
}
if(res == NSAlertFirstButtonReturn) {
[NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
_isQuitting = YES;
}
}];
return;
}
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
NSInteger status = httpResponse.statusCode;
if(status == 200) {
NSLog(@"leave ok");
}
else if (status == 401) {
self->_resetKey = YES;
}
else {
NSLog(@"leave error: %ld", status);
}
}];
[task resume];
}
@end

View file

@ -0,0 +1,36 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
@class NetworkMonitor;
@class Network;
@interface ShowNetworksViewController : NSViewController<NSTableViewDelegate, NSTableViewDataSource>
@property (nonatomic) NSMutableArray<Network*> *networkList;
@property (nonatomic) NetworkMonitor *netMonitor;
@property (nonatomic) BOOL visible;
@property (weak, nonatomic) IBOutlet NSTableView *tableView;
- (void)deleteNetworkFromList:(NSString*)nwid;
- (void)setNetworks:(NSArray<Network*>*)list;
@end

View file

@ -0,0 +1,184 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import "ShowNetworksViewController.h"
#import "NetworkMonitor.h"
#import "NetworkInfoCell.h"
#import "Network.h"
BOOL hasNetworkWithID(NSArray<Network*> *list, UInt64 nwid)
{
for(Network *n in list) {
if(n.nwid == nwid) {
return YES;
}
}
return NO;
}
@interface ShowNetworksViewController ()
@end
@implementation ShowNetworksViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.networkList = [NSMutableArray array];
[self.tableView setDelegate:self];
[self.tableView setDataSource:self];
[self.tableView setBackgroundColor:[NSColor clearColor]];
}
- (void)viewWillAppear {
[super viewWillAppear];
self.visible = YES;
}
- (void)viewWillDisappear {
[super viewWillDisappear];
self.visible = NO;
}
- (NSInteger)findNetworkWithID:(UInt64)networkId
{
for(int i = 0; i < [_networkList count]; ++i) {
Network *nw = [_networkList objectAtIndex:i];
if(nw.nwid == networkId) {
return i;
}
}
return NSNotFound;
}
- (void)deleteNetworkFromList:(NSString *)nwid {
[self.netMonitor deleteSavedNetwork:nwid];
UInt64 netid = 0;
NSScanner *scanner = [NSScanner scannerWithString:nwid];
[scanner scanHexLongLong:&netid];
for (Network *n in _networkList) {
if (n.nwid == netid) {
NSInteger index = [self findNetworkWithID:netid];
if (index != NSNotFound) {
[_networkList removeObjectAtIndex:index];
[_tableView reloadData];
}
}
}
}
- (void)setNetworks:(NSArray<Network *> *)list {
for (Network *n in list) {
if ([_networkList containsObject:n]) {
// don't need to do anything here. Already an identical object in the list
continue;
}
else {
// network not in the list based on equality. Did an object change? or is it a new item?
if (hasNetworkWithID(_networkList, n.nwid)) {
for (int i = 0; i < [_networkList count]; ++i) {
Network *n2 = [_networkList objectAtIndex:i];
if (n.nwid == n2.nwid)
{
[_networkList replaceObjectAtIndex:i withObject:n];
[_tableView reloadDataForRowIndexes:[NSIndexSet indexSetWithIndex:i]
columnIndexes:[NSIndexSet indexSetWithIndex:0]];
}
}
}
else {
[_networkList addObject:n];
[_tableView reloadData];
}
}
}
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return [_networkList count];
}
- (NSView*)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
NetworkInfoCell *cell = (NetworkInfoCell*)[tableView makeViewWithIdentifier:@"NetworkInfoCell"
owner:nil];
Network *network = [_networkList objectAtIndex:row];
cell.parent = self;
cell.networkIdField.stringValue = [NSString stringWithFormat:@"%10llx", network.nwid];
cell.networkNameField.stringValue = network.name;
cell.statusField.stringValue = [network statusString];
cell.typeField.stringValue = [network typeString];
cell.mtuField.stringValue = [NSString stringWithFormat:@"%d", network.mtu];
cell.macField.stringValue = network.mac;
cell.broadcastField.stringValue = network.broadcastEnabled ? @"ENABLED" : @"DISABLED";
cell.bridgingField.stringValue = network.bridge ? @"ENABLED" : @"DISABLED";
cell.deviceField.stringValue = network.portDeviceName;
if(network.connected) {
cell.connectedCheckbox.state = NSOnState;
if(network.allowDefault) {
cell.allowDefault.enabled = YES;
cell.allowDefault.state = NSOnState;
}
else {
cell.allowDefault.state = NSOffState;
if([Network defaultRouteExists:_networkList]) {
cell.allowDefault.enabled = NO;
}
else {
cell.allowDefault.enabled = YES;
}
}
cell.allowGlobal.enabled = YES;
cell.allowManaged.enabled = YES;
cell.allowDNS.enabled = YES;
}
else {
cell.connectedCheckbox.state = NSOffState;
cell.allowDefault.enabled = NO;
cell.allowGlobal.enabled = NO;
cell.allowManaged.enabled = NO;
cell.allowDNS.enabled = NO;
}
cell.allowGlobal.state = network.allowGlobal ? NSOnState : NSOffState;
cell.allowManaged.state = network.allowManaged ? NSOnState : NSOffState;
cell.allowDNS.state = network.allowDNS ? NSOnState : NSOffState;
cell.addressesField.stringValue = @"";
for(NSString *addr in network.assignedAddresses) {
cell.addressesField.stringValue = [[cell.addressesField.stringValue stringByAppendingString:addr] stringByAppendingString:@"\n"];
}
return cell;
}
@end

View file

@ -0,0 +1,394 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="16097.3" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16097.3"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="ShowNetworksViewController" customModule="ZeroTier_One" customModuleProvider="target">
<connections>
<outlet property="tableView" destination="w5O-vn-cYB" id="Ud6-Bs-UFB"/>
<outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView id="Hz6-mo-xeY">
<rect key="frame" x="0.0" y="0.0" width="570" height="521"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="390" horizontalPageScroll="10" verticalLineScroll="390" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="miH-DQ-i4L">
<rect key="frame" x="20" y="20" width="530" height="481"/>
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="KXW-dX-mx6">
<rect key="frame" x="0.0" y="0.0" width="530" height="481"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="none" columnReordering="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="388" rowSizeStyle="automatic" viewBased="YES" id="w5O-vn-cYB">
<rect key="frame" x="0.0" y="0.0" width="530" height="481"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.59999999999999998" colorSpace="calibratedRGB"/>
<tableViewGridLines key="gridStyleMask" horizontal="YES"/>
<color key="gridColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
<tableColumns>
<tableColumn width="527" minWidth="40" maxWidth="1000" id="ztK-JB-A6Q">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="WAX-7a-M9n">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView identifier="NetworkInfoCell" focusRingType="none" id="rmb-il-W5I" customClass="NetworkInfoCell">
<rect key="frame" x="1" y="1" width="527" height="388"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="EUT-1A-lgY">
<rect key="frame" x="480" y="370" width="44" height="15"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" title="Label" id="bf8-gi-tpp">
<font key="font" size="13" name="AndaleMono"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="UAC-7B-K8Y">
<rect key="frame" x="55" y="346" width="43" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Status" id="KgQ-AO-0Us">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="FeX-UV-AFG">
<rect key="frame" x="64" y="322" width="34" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Type" id="8OM-iG-575">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LIA-GW-caM">
<rect key="frame" x="65" y="298" width="33" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="MAC" id="UK0-f8-L0U">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="EWq-81-Y6j">
<rect key="frame" x="65" y="274" width="33" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="MTU" id="5Wi-02-yNW">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Mi3-aV-yWg">
<rect key="frame" x="32" y="250" width="66" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Broadcast" id="b7V-FV-HH7">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="EKG-la-snQ">
<rect key="frame" x="43" y="226" width="55" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Bridging" id="bkm-pp-3tu">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="wl2-R8-KQO">
<rect key="frame" x="480" y="347" width="44" height="15"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Label" id="fkd-z8-2sv">
<font key="font" size="13" name="AndaleMono"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6rE-7R-shM">
<rect key="frame" x="1" y="202" width="97" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Allow Managed" id="AOv-4I-rQj">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dke-gy-mG0">
<rect key="frame" x="14" y="154" width="84" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Allow Default" id="SIi-Uu-Uzw">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button translatesAutoresizingMaskIntoConstraints="NO" id="ulU-Mk-uV9">
<rect key="frame" x="504" y="201" width="22" height="18"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Zhe-BT-cXO">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="onAllowStatusChanged:" target="rmb-il-W5I" id="FW8-5N-vt1"/>
</connections>
</button>
<button translatesAutoresizingMaskIntoConstraints="NO" id="8CS-6g-NFI">
<rect key="frame" x="504" y="153" width="22" height="18"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" inset="2" id="S2d-lU-JhT">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="onAllowStatusChanged:" target="rmb-il-W5I" id="ahh-N8-nhW"/>
</connections>
</button>
<button translatesAutoresizingMaskIntoConstraints="NO" id="URn-qw-7jG">
<rect key="frame" x="504" y="177" width="22" height="18"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" inset="2" id="yBQ-2g-3t5">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="onAllowStatusChanged:" target="rmb-il-W5I" id="XGy-pE-Dzf"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jdz-W3-UwS">
<rect key="frame" x="19" y="178" width="79" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Allow Global" id="PLj-4F-ROh">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dou-E5-8PF">
<rect key="frame" x="480" y="323" width="44" height="15"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Label" id="3Dq-d7-Gt3">
<font key="font" size="13" name="AndaleMono"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oD0-Qh-7L4">
<rect key="frame" x="480" y="299" width="44" height="15"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Label" id="35o-HJ-KYh">
<font key="font" size="13" name="AndaleMono"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="98C-J0-Y03">
<rect key="frame" x="480" y="275" width="44" height="15"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Label" id="63c-hy-MHZ">
<font key="font" size="13" name="AndaleMono"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="la4-uE-ffj">
<rect key="frame" x="480" y="251" width="44" height="15"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Label" id="rtd-6E-MsN">
<font key="font" size="13" name="AndaleMono"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qHh-oP-Tdb">
<rect key="frame" x="480" y="227" width="44" height="15"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Label" id="Hex-iJ-2by">
<font key="font" size="13" name="AndaleMono"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lO9-Jg-9f8">
<rect key="frame" x="1" y="370" width="44" height="15"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" title="Label" id="p7O-rs-RvR">
<font key="font" size="13" name="AndaleMono"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="LVO-pV-uxK">
<rect key="frame" x="504" y="129" width="22" height="18"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" inset="2" id="p18-jj-cZY">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="onAllowStatusChanged:" target="rmb-il-W5I" id="5oT-2l-MKp"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="aQh-Pm-LJ5">
<rect key="frame" x="30" y="130" width="68" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Allow DNS" id="wrx-kd-ZBc">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="syI-eg-Zka">
<rect key="frame" x="52" y="107" width="46" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Device" id="3tY-hy-qbu">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6Af-7O-CaP">
<rect key="frame" x="16" y="83" width="82" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Managed IPs" id="wHt-u2-7XG">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="AiO-ZR-9A3">
<rect key="frame" x="-3" y="7" width="134" height="32"/>
<buttonCell key="cell" type="push" title="Delete Network" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="7Dg-VG-hjC">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="deleteNetwork:" target="rmb-il-W5I" id="gBI-fk-OoF"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="C0q-lJ-5dX">
<rect key="frame" x="480" y="108" width="44" height="15"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Label" id="5Ms-FS-k0W">
<font key="font" size="13" name="AndaleMono"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="GEJ-6D-gWU">
<rect key="frame" x="102" y="85" width="424" height="15"/>
<textFieldCell key="cell" selectable="YES" sendsActionOnEndEditing="YES" alignment="right" title="Multiline Label" id="A3M-ZZ-6h7">
<font key="font" size="13" name="AndaleMono"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button translatesAutoresizingMaskIntoConstraints="NO" id="KRe-B1-51k">
<rect key="frame" x="437" y="16" width="89" height="18"/>
<buttonCell key="cell" type="check" title="Connected" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="DWJ-ZT-UIa">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="onConnectCheckStateChanged:" target="rmb-il-W5I" id="Ov2-bq-67i"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="LIA-GW-caM" firstAttribute="trailing" secondItem="EWq-81-Y6j" secondAttribute="trailing" id="0vU-gw-esB"/>
<constraint firstItem="FeX-UV-AFG" firstAttribute="trailing" secondItem="LIA-GW-caM" secondAttribute="trailing" id="1xy-N5-B6U"/>
<constraint firstItem="FeX-UV-AFG" firstAttribute="top" secondItem="UAC-7B-K8Y" secondAttribute="bottom" constant="8" id="2Vh-D6-T45"/>
<constraint firstItem="qHh-oP-Tdb" firstAttribute="centerY" secondItem="EKG-la-snQ" secondAttribute="centerY" id="4xy-tk-eA7"/>
<constraint firstItem="LIA-GW-caM" firstAttribute="top" secondItem="FeX-UV-AFG" secondAttribute="bottom" constant="8" id="5Vd-2M-2yv"/>
<constraint firstAttribute="bottom" secondItem="AiO-ZR-9A3" secondAttribute="bottom" constant="14" id="6fF-tf-eNL"/>
<constraint firstItem="syI-eg-Zka" firstAttribute="top" secondItem="aQh-Pm-LJ5" secondAttribute="bottom" constant="7" id="6rF-6f-NLD"/>
<constraint firstItem="dou-E5-8PF" firstAttribute="centerY" secondItem="FeX-UV-AFG" secondAttribute="centerY" id="7iQ-Vx-9AJ"/>
<constraint firstItem="aQh-Pm-LJ5" firstAttribute="trailing" secondItem="dke-gy-mG0" secondAttribute="trailing" id="Avt-CD-fbX"/>
<constraint firstAttribute="trailing" secondItem="wl2-R8-KQO" secondAttribute="trailing" constant="5" id="CaI-uw-8uL"/>
<constraint firstItem="Mi3-aV-yWg" firstAttribute="top" secondItem="EWq-81-Y6j" secondAttribute="bottom" constant="8" id="Cen-A6-Hdr"/>
<constraint firstItem="URn-qw-7jG" firstAttribute="centerY" secondItem="jdz-W3-UwS" secondAttribute="centerY" id="DEW-3F-MXB"/>
<constraint firstAttribute="trailing" secondItem="GEJ-6D-gWU" secondAttribute="trailing" constant="3" id="FC0-J7-2QF"/>
<constraint firstItem="EWq-81-Y6j" firstAttribute="trailing" secondItem="Mi3-aV-yWg" secondAttribute="trailing" id="FDe-x8-ERi"/>
<constraint firstItem="LVO-pV-uxK" firstAttribute="centerY" secondItem="aQh-Pm-LJ5" secondAttribute="centerY" id="FK7-6N-9It"/>
<constraint firstAttribute="trailing" secondItem="qHh-oP-Tdb" secondAttribute="trailing" constant="5" id="Fcy-KL-LsD"/>
<constraint firstAttribute="trailing" secondItem="C0q-lJ-5dX" secondAttribute="trailing" constant="5" id="I3g-Oy-geM"/>
<constraint firstItem="EUT-1A-lgY" firstAttribute="top" secondItem="rmb-il-W5I" secondAttribute="top" constant="3" id="II4-Ta-EeQ"/>
<constraint firstItem="98C-J0-Y03" firstAttribute="centerY" secondItem="EWq-81-Y6j" secondAttribute="centerY" id="Ibd-3u-9fm"/>
<constraint firstAttribute="trailing" secondItem="8CS-6g-NFI" secondAttribute="trailing" constant="3" id="Jqv-Kb-lOT"/>
<constraint firstAttribute="trailing" secondItem="dou-E5-8PF" secondAttribute="trailing" constant="5" id="LPR-aD-BAP"/>
<constraint firstItem="jdz-W3-UwS" firstAttribute="top" secondItem="6rE-7R-shM" secondAttribute="bottom" constant="8" id="Lit-Zb-6pq"/>
<constraint firstItem="UAC-7B-K8Y" firstAttribute="top" secondItem="lO9-Jg-9f8" secondAttribute="bottom" constant="8" id="Mn0-LO-gSb"/>
<constraint firstItem="la4-uE-ffj" firstAttribute="centerY" secondItem="Mi3-aV-yWg" secondAttribute="centerY" id="Nhp-8t-OoR"/>
<constraint firstItem="lO9-Jg-9f8" firstAttribute="leading" secondItem="rmb-il-W5I" secondAttribute="leading" constant="3" id="Rzw-sT-s3c"/>
<constraint firstAttribute="trailing" secondItem="la4-uE-ffj" secondAttribute="trailing" constant="5" id="SQo-oO-lbs"/>
<constraint firstItem="AiO-ZR-9A3" firstAttribute="top" secondItem="6Af-7O-CaP" secondAttribute="bottom" constant="48" id="SbW-ma-xhO"/>
<constraint firstItem="wl2-R8-KQO" firstAttribute="centerY" secondItem="UAC-7B-K8Y" secondAttribute="centerY" id="TIS-fV-H3y"/>
<constraint firstItem="C0q-lJ-5dX" firstAttribute="centerY" secondItem="syI-eg-Zka" secondAttribute="centerY" id="TXe-Dr-AUr"/>
<constraint firstItem="lO9-Jg-9f8" firstAttribute="top" secondItem="rmb-il-W5I" secondAttribute="top" constant="3" id="TqS-9j-AZ2"/>
<constraint firstAttribute="trailing" secondItem="oD0-Qh-7L4" secondAttribute="trailing" constant="5" id="U1G-04-Zjb"/>
<constraint firstItem="jdz-W3-UwS" firstAttribute="trailing" secondItem="6rE-7R-shM" secondAttribute="trailing" id="UWD-yZ-0gu"/>
<constraint firstItem="EWq-81-Y6j" firstAttribute="top" secondItem="LIA-GW-caM" secondAttribute="bottom" constant="8" id="WS4-Xr-Uvt"/>
<constraint firstItem="GEJ-6D-gWU" firstAttribute="top" secondItem="C0q-lJ-5dX" secondAttribute="bottom" constant="8" id="WhD-XW-q7s"/>
<constraint firstAttribute="trailing" secondItem="KRe-B1-51k" secondAttribute="trailing" constant="3" id="WsQ-kS-Luf"/>
<constraint firstItem="8CS-6g-NFI" firstAttribute="centerY" secondItem="dke-gy-mG0" secondAttribute="centerY" id="X1u-9J-gLq"/>
<constraint firstItem="EKG-la-snQ" firstAttribute="top" secondItem="Mi3-aV-yWg" secondAttribute="bottom" constant="8" id="XEZ-4d-Yl9"/>
<constraint firstItem="6Af-7O-CaP" firstAttribute="top" secondItem="syI-eg-Zka" secondAttribute="bottom" constant="8" id="Xi3-aV-ZPe"/>
<constraint firstAttribute="trailing" secondItem="EUT-1A-lgY" secondAttribute="trailing" constant="5" id="cDU-PD-iMu"/>
<constraint firstItem="6rE-7R-shM" firstAttribute="leading" secondItem="rmb-il-W5I" secondAttribute="leading" constant="3" id="cIK-gU-COR"/>
<constraint firstItem="6Af-7O-CaP" firstAttribute="trailing" secondItem="syI-eg-Zka" secondAttribute="trailing" id="gP2-re-FqN"/>
<constraint firstAttribute="trailing" secondItem="98C-J0-Y03" secondAttribute="trailing" constant="5" id="ghX-kA-tEa"/>
<constraint firstItem="UAC-7B-K8Y" firstAttribute="trailing" secondItem="FeX-UV-AFG" secondAttribute="trailing" id="hOJ-rF-Xn8"/>
<constraint firstItem="GEJ-6D-gWU" firstAttribute="leading" secondItem="6Af-7O-CaP" secondAttribute="trailing" constant="8" id="iBi-dY-iZi"/>
<constraint firstItem="KRe-B1-51k" firstAttribute="baseline" secondItem="AiO-ZR-9A3" secondAttribute="baseline" id="jBe-rC-QAF"/>
<constraint firstItem="ulU-Mk-uV9" firstAttribute="centerY" secondItem="6rE-7R-shM" secondAttribute="centerY" id="l5g-Dr-Bht"/>
<constraint firstItem="6rE-7R-shM" firstAttribute="top" secondItem="EKG-la-snQ" secondAttribute="bottom" constant="8" id="lvp-Dn-1m0"/>
<constraint firstAttribute="trailing" secondItem="KRe-B1-51k" secondAttribute="trailing" constant="3" id="pZ7-4k-n3s"/>
<constraint firstItem="AiO-ZR-9A3" firstAttribute="leading" secondItem="rmb-il-W5I" secondAttribute="leading" constant="3" id="pau-hs-aaF"/>
<constraint firstItem="aQh-Pm-LJ5" firstAttribute="top" secondItem="dke-gy-mG0" secondAttribute="bottom" constant="8" id="pkv-6I-GJ6"/>
<constraint firstItem="dke-gy-mG0" firstAttribute="trailing" secondItem="jdz-W3-UwS" secondAttribute="trailing" id="qd7-UW-evp"/>
<constraint firstItem="dke-gy-mG0" firstAttribute="top" secondItem="jdz-W3-UwS" secondAttribute="bottom" constant="8" id="sHm-Jz-ko8"/>
<constraint firstItem="EKG-la-snQ" firstAttribute="trailing" secondItem="6rE-7R-shM" secondAttribute="trailing" id="tNY-Wb-Aig"/>
<constraint firstAttribute="trailing" secondItem="URn-qw-7jG" secondAttribute="trailing" constant="3" id="tb8-cb-vhf"/>
<constraint firstAttribute="trailing" secondItem="ulU-Mk-uV9" secondAttribute="trailing" constant="3" id="vCN-jZ-bH7"/>
<constraint firstItem="oD0-Qh-7L4" firstAttribute="centerY" secondItem="LIA-GW-caM" secondAttribute="centerY" id="vol-qx-psh"/>
<constraint firstAttribute="trailing" secondItem="LVO-pV-uxK" secondAttribute="trailing" constant="3" id="xJ5-qj-Pba"/>
<constraint firstItem="syI-eg-Zka" firstAttribute="trailing" secondItem="aQh-Pm-LJ5" secondAttribute="trailing" id="yLe-a7-uDd"/>
<constraint firstItem="Mi3-aV-yWg" firstAttribute="trailing" secondItem="EKG-la-snQ" secondAttribute="trailing" id="yWV-G4-bDS"/>
</constraints>
<connections>
<outlet property="addressesField" destination="GEJ-6D-gWU" id="MDn-cx-TNx"/>
<outlet property="allowDNS" destination="LVO-pV-uxK" id="OCm-dc-5UI"/>
<outlet property="allowDefault" destination="8CS-6g-NFI" id="YLt-Gp-HNa"/>
<outlet property="allowGlobal" destination="URn-qw-7jG" id="VUy-Mh-nK4"/>
<outlet property="allowManaged" destination="ulU-Mk-uV9" id="poZ-5E-m0m"/>
<outlet property="bridgingField" destination="qHh-oP-Tdb" id="eSw-Dw-QoN"/>
<outlet property="broadcastField" destination="la4-uE-ffj" id="A89-yC-MhR"/>
<outlet property="connectedCheckbox" destination="KRe-B1-51k" id="Sz5-Fq-jWL"/>
<outlet property="deleteButton" destination="AiO-ZR-9A3" id="rYp-Vt-gHl"/>
<outlet property="deviceField" destination="C0q-lJ-5dX" id="bc1-Fh-zT8"/>
<outlet property="macField" destination="oD0-Qh-7L4" id="4TS-1J-vRK"/>
<outlet property="mtuField" destination="98C-J0-Y03" id="KTM-C4-bEQ"/>
<outlet property="networkIdField" destination="lO9-Jg-9f8" id="UlQ-yf-ZYk"/>
<outlet property="networkNameField" destination="EUT-1A-lgY" id="Kwa-OJ-LTB"/>
<outlet property="statusField" destination="wl2-R8-KQO" id="fH2-Wl-DtW"/>
<outlet property="typeField" destination="dou-E5-8PF" id="v6U-sw-kzs"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
</tableColumns>
</tableView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.59999999999999998" colorSpace="calibratedRGB"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="ySn-XX-fde">
<rect key="frame" x="1" y="256" width="478" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="be6-Ft-7fo">
<rect key="frame" x="224" y="17" width="15" height="102"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="miH-DQ-i4L" secondAttribute="trailing" constant="20" id="453-vf-nVL"/>
<constraint firstItem="miH-DQ-i4L" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="20" id="IS6-3U-KHq"/>
<constraint firstAttribute="bottom" secondItem="miH-DQ-i4L" secondAttribute="bottom" constant="20" id="YIB-OP-keG"/>
<constraint firstItem="miH-DQ-i4L" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" constant="20" id="ceZ-7I-uoc"/>
</constraints>
<point key="canvasLocation" x="220" y="323.5"/>
</customView>
</objects>
</document>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
</plist>

Binary file not shown.

View file

@ -0,0 +1,58 @@
<html>
<head>
<style type="text/css">
html,body {
background: #ffffff;
margin: 0;
padding: 0;
font-family: sans-serif;
font-size: 12pt;
height: 100%;
width: 100%;
}
div.icon {
background: #ffb354;
color: #000000;
font-size: 100pt;
border-radius: 2.5rem;
display: inline-block;
width: 1.3em;
height: 1.3em;
padding: 0;
margin: 0;
line-height: 1.4em;
vertical-align: middle;
text-align: center;
}
div.icon_container {
font-weight: bold;
}
a,p,h1,h2,h3,h4,span,div,strong,center,lead,nav,ol,ul,li,img,button,input,textarea,form {
font-family: sans-serif;
}
.code {
font-family: "Menlo",monospace !important;
}
a:link {
text-decoration: none;
}
</style>
</head>
<body>
<center><div class="icon_container"><div class="icon">&#x23c1;</div></div></center>
<div>
<h2>Welcome to ZeroTier</h2>
<h4>Getting Started</h4>
<p>Networks are identified by 16-digit network IDs. If someone invited you to join theirs you probably received one. If not you can create your own at <a href="https://my.zerotier.com/">my.zerotier.com</a> or by running <a href="https://github.com/zerotier/ZeroTierOne/tree/master/controller">running your own network controller</a>.
<p>Your computer is identified by a 10-digit ZeroTier address. You can find it at the top of the ZeroTier app's pull-down menu or by typing <span class="code">"sudo zerotier-cli info"</span> in a terminal window. This number is unique to your system and is how network administrators can recognize you. If someone invited you to a network, give them this ID so they can authorize you to join.</p>
<h4>Starting, Stopping, and Uninstalling</h4>
<p>The ZeroTier service is separate from the UI app and starts on system boot. The app can be started on login or only when needed. To stop the ZeroTier service use:<br><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="code">sudo launchctl unload /Library/LaunchDaemons/com.zerotier.one.plist</span><br><br>
Replace "unload" with "load" to start it again.</p>
<p>ZeroTier can be uninstalled with:<br><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="code">sudo '/Library/Application Support/ZeroTier/One/uninstall.sh'
</p>
<p><b>For more information, visit <a href="http://www.zerotier.com">zerotier.com</a>.</b></p>
</div>
</body>
</html>

View file

@ -0,0 +1,23 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
int main(int argc, const char * argv[]) {
return NSApplicationMain(argc, argv);
}