initial checkin!
|
@ -0,0 +1,414 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
7D17C4E51D658D9F0066232A /* AboutWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D17C4D81D658D9F0066232A /* AboutWindow.xib */; };
|
||||
7D17C4E61D658D9F0066232A /* AboutWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17C4DA1D658D9F0066232A /* AboutWindowController.m */; };
|
||||
7D17C4E71D658D9F0066232A /* Exception.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17C4DD1D658D9F0066232A /* Exception.m */; };
|
||||
7D17C4E81D658D9F0066232A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 7D17C4DF1D658D9F0066232A /* icon.png */; };
|
||||
7D17C4E91D658D9F0066232A /* overSight.png in Resources */ = {isa = PBXBuildFile; fileRef = 7D17C4E01D658D9F0066232A /* overSight.png */; };
|
||||
7D17C4EA1D658D9F0066232A /* Logging.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17C4E21D658D9F0066232A /* Logging.m */; };
|
||||
7D17C4EB1D658D9F0066232A /* Utilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17C4E41D658D9F0066232A /* Utilities.m */; };
|
||||
7D17C4F91D658DB90066232A /* Configure.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17C4EC1D658DB90066232A /* Configure.m */; };
|
||||
7D17C4FA1D658DB90066232A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17C4ED1D658DB90066232A /* AppDelegate.m */; };
|
||||
7D17C4FB1D658DB90066232A /* ConfigureWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17C4EE1D658DB90066232A /* ConfigureWindowController.m */; };
|
||||
7D17C4FC1D658DB90066232A /* ConfigureWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D17C4EF1D658DB90066232A /* ConfigureWindowController.xib */; };
|
||||
7D17C4FD1D658DB90066232A /* ErrorWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17C4F31D658DB90066232A /* ErrorWindowController.m */; };
|
||||
7D17C4FE1D658DB90066232A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17C4F41D658DB90066232A /* main.m */; };
|
||||
7D17C4FF1D658DB90066232A /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7D17C4F51D658DB90066232A /* Info.plist */; };
|
||||
7D17C5001D658DB90066232A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7D17C4F71D658DB90066232A /* Assets.xcassets */; };
|
||||
7D17C5011D658DB90066232A /* ErrorWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D17C4F81D658DB90066232A /* ErrorWindowController.xib */; };
|
||||
7D17C5041D658DEC0066232A /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D17C5021D658DEC0066232A /* MainMenu.xib */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
7D17C4D81D658D9F0066232A /* AboutWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AboutWindow.xib; sourceTree = "<group>"; };
|
||||
7D17C4D91D658D9F0066232A /* AboutWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AboutWindowController.h; sourceTree = "<group>"; };
|
||||
7D17C4DA1D658D9F0066232A /* AboutWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AboutWindowController.m; sourceTree = "<group>"; };
|
||||
7D17C4DB1D658D9F0066232A /* Consts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Consts.h; sourceTree = "<group>"; };
|
||||
7D17C4DC1D658D9F0066232A /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = "<group>"; };
|
||||
7D17C4DD1D658D9F0066232A /* Exception.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Exception.m; sourceTree = "<group>"; };
|
||||
7D17C4DF1D658D9F0066232A /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon.png; sourceTree = "<group>"; };
|
||||
7D17C4E01D658D9F0066232A /* overSight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = overSight.png; sourceTree = "<group>"; };
|
||||
7D17C4E11D658D9F0066232A /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Logging.h; sourceTree = "<group>"; };
|
||||
7D17C4E21D658D9F0066232A /* Logging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Logging.m; sourceTree = "<group>"; };
|
||||
7D17C4E31D658D9F0066232A /* Utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utilities.h; sourceTree = "<group>"; };
|
||||
7D17C4E41D658D9F0066232A /* Utilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Utilities.m; sourceTree = "<group>"; };
|
||||
7D17C4EC1D658DB90066232A /* Configure.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Configure.m; path = Installer/Configure.m; sourceTree = SOURCE_ROOT; };
|
||||
7D17C4ED1D658DB90066232A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Installer/AppDelegate.m; sourceTree = SOURCE_ROOT; };
|
||||
7D17C4EE1D658DB90066232A /* ConfigureWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ConfigureWindowController.m; path = Installer/ConfigureWindowController.m; sourceTree = SOURCE_ROOT; };
|
||||
7D17C4EF1D658DB90066232A /* ConfigureWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = ConfigureWindowController.xib; path = Installer/ConfigureWindowController.xib; sourceTree = SOURCE_ROOT; };
|
||||
7D17C4F01D658DB90066232A /* Configure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Configure.h; path = Installer/Configure.h; sourceTree = SOURCE_ROOT; };
|
||||
7D17C4F11D658DB90066232A /* ConfigureWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConfigureWindowController.h; path = Installer/ConfigureWindowController.h; sourceTree = SOURCE_ROOT; };
|
||||
7D17C4F21D658DB90066232A /* ErrorWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ErrorWindowController.h; path = Installer/ErrorWindowController.h; sourceTree = SOURCE_ROOT; };
|
||||
7D17C4F31D658DB90066232A /* ErrorWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ErrorWindowController.m; path = Installer/ErrorWindowController.m; sourceTree = SOURCE_ROOT; };
|
||||
7D17C4F41D658DB90066232A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Installer/main.m; sourceTree = SOURCE_ROOT; };
|
||||
7D17C4F51D658DB90066232A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Installer/Info.plist; sourceTree = SOURCE_ROOT; };
|
||||
7D17C4F61D658DB90066232A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Installer/AppDelegate.h; sourceTree = SOURCE_ROOT; };
|
||||
7D17C4F71D658DB90066232A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Installer/Assets.xcassets; sourceTree = SOURCE_ROOT; };
|
||||
7D17C4F81D658DB90066232A /* ErrorWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = ErrorWindowController.xib; path = Installer/ErrorWindowController.xib; sourceTree = SOURCE_ROOT; };
|
||||
7D17C5031D658DEC0066232A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Installer/Base.lproj/MainMenu.xib; sourceTree = SOURCE_ROOT; };
|
||||
7D24C8651D2CDEA7009932EE /* Installer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Installer.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
7D24C8621D2CDEA7009932EE /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
7D17C4D71D658D9F0066232A /* Shared */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7D17C4D81D658D9F0066232A /* AboutWindow.xib */,
|
||||
7D17C4D91D658D9F0066232A /* AboutWindowController.h */,
|
||||
7D17C4DA1D658D9F0066232A /* AboutWindowController.m */,
|
||||
7D17C4DB1D658D9F0066232A /* Consts.h */,
|
||||
7D17C4DC1D658D9F0066232A /* Exception.h */,
|
||||
7D17C4DD1D658D9F0066232A /* Exception.m */,
|
||||
7D17C4DE1D658D9F0066232A /* Images */,
|
||||
7D17C4E11D658D9F0066232A /* Logging.h */,
|
||||
7D17C4E21D658D9F0066232A /* Logging.m */,
|
||||
7D17C4E31D658D9F0066232A /* Utilities.h */,
|
||||
7D17C4E41D658D9F0066232A /* Utilities.m */,
|
||||
);
|
||||
path = Shared;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7D17C4DE1D658D9F0066232A /* Images */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7D17C4DF1D658D9F0066232A /* icon.png */,
|
||||
7D17C4E01D658D9F0066232A /* overSight.png */,
|
||||
);
|
||||
path = Images;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7D17C5051D658F3E0066232A /* Images */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
name = Images;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7D24C85C1D2CDEA7009932EE = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7D17C5051D658F3E0066232A /* Images */,
|
||||
7D17C4D71D658D9F0066232A /* Shared */,
|
||||
7D24C8671D2CDEA7009932EE /* Source */,
|
||||
7D24C8661D2CDEA7009932EE /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7D24C8661D2CDEA7009932EE /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7D24C8651D2CDEA7009932EE /* Installer.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7D24C8671D2CDEA7009932EE /* Source */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7D17C5021D658DEC0066232A /* MainMenu.xib */,
|
||||
7D17C4EC1D658DB90066232A /* Configure.m */,
|
||||
7D17C4ED1D658DB90066232A /* AppDelegate.m */,
|
||||
7D17C4EE1D658DB90066232A /* ConfigureWindowController.m */,
|
||||
7D17C4EF1D658DB90066232A /* ConfigureWindowController.xib */,
|
||||
7D17C4F01D658DB90066232A /* Configure.h */,
|
||||
7D17C4F11D658DB90066232A /* ConfigureWindowController.h */,
|
||||
7D17C4F21D658DB90066232A /* ErrorWindowController.h */,
|
||||
7D17C4F31D658DB90066232A /* ErrorWindowController.m */,
|
||||
7D17C4F61D658DB90066232A /* AppDelegate.h */,
|
||||
7D17C4F71D658DB90066232A /* Assets.xcassets */,
|
||||
7D17C4F81D658DB90066232A /* ErrorWindowController.xib */,
|
||||
7D24C86B1D2CDEA7009932EE /* Supporting Files */,
|
||||
);
|
||||
name = Source;
|
||||
path = WhatsYourSign;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7D24C86B1D2CDEA7009932EE /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7D17C4F51D658DB90066232A /* Info.plist */,
|
||||
7D17C4F41D658DB90066232A /* main.m */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
7D24C8641D2CDEA7009932EE /* Installer */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 7D24C8761D2CDEA7009932EE /* Build configuration list for PBXNativeTarget "Installer" */;
|
||||
buildPhases = (
|
||||
7D24C8611D2CDEA7009932EE /* Sources */,
|
||||
7D24C8621D2CDEA7009932EE /* Frameworks */,
|
||||
7D24C8631D2CDEA7009932EE /* Resources */,
|
||||
7D1A49C71D502D4A000E2BEB /* ShellScript */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Installer;
|
||||
productName = WhatsYourSign;
|
||||
productReference = 7D24C8651D2CDEA7009932EE /* Installer.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
7D24C85D1D2CDEA7009932EE /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0730;
|
||||
ORGANIZATIONNAME = "Objective-See";
|
||||
TargetAttributes = {
|
||||
7D24C8641D2CDEA7009932EE = {
|
||||
CreatedOnToolsVersion = 7.3;
|
||||
DevelopmentTeam = VBG97UB4TA;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 7D24C8601D2CDEA7009932EE /* Build configuration list for PBXProject "Installer" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 7D24C85C1D2CDEA7009932EE;
|
||||
productRefGroup = 7D24C8661D2CDEA7009932EE /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
7D24C8641D2CDEA7009932EE /* Installer */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
7D24C8631D2CDEA7009932EE /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
7D17C4E91D658D9F0066232A /* overSight.png in Resources */,
|
||||
7D17C4FF1D658DB90066232A /* Info.plist in Resources */,
|
||||
7D17C5011D658DB90066232A /* ErrorWindowController.xib in Resources */,
|
||||
7D17C5001D658DB90066232A /* Assets.xcassets in Resources */,
|
||||
7D17C4E81D658D9F0066232A /* icon.png in Resources */,
|
||||
7D17C4FC1D658DB90066232A /* ConfigureWindowController.xib in Resources */,
|
||||
7D17C4E51D658D9F0066232A /* AboutWindow.xib in Resources */,
|
||||
7D17C5041D658DEC0066232A /* MainMenu.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
7D1A49C71D502D4A000E2BEB /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "#cp -R -f $BUILT_PRODUCTS_DIR/WhatsYourSign.appex $BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Resources/WhatsYourSign.appex\n\n#for achiving\n# ->first build finder sync in release mode (don't archive it)\n# then archive (this) installer app\n#cp -R -f ~/objective-see/WhatsYourSign/DerivedData/WhatsYourSign/Build/Products/Release/WhatsYourSign.appex ~/objective-see/WhatsYourSign/DerivedData/WhatsYourSign/Build/Intermediates/ArchiveIntermediates/WhatsYourSign/BuildProductsPath/Release/WhatsYourSign.app/Contents/Resources/WhatsYourSign.appex\n";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
7D24C8611D2CDEA7009932EE /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
7D17C4FB1D658DB90066232A /* ConfigureWindowController.m in Sources */,
|
||||
7D17C4FA1D658DB90066232A /* AppDelegate.m in Sources */,
|
||||
7D17C4E71D658D9F0066232A /* Exception.m in Sources */,
|
||||
7D17C4EB1D658D9F0066232A /* Utilities.m in Sources */,
|
||||
7D17C4F91D658DB90066232A /* Configure.m in Sources */,
|
||||
7D17C4EA1D658D9F0066232A /* Logging.m in Sources */,
|
||||
7D17C4FD1D658DB90066232A /* ErrorWindowController.m in Sources */,
|
||||
7D17C4FE1D658DB90066232A /* main.m in Sources */,
|
||||
7D17C4E61D658D9F0066232A /* AboutWindowController.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
7D17C5021D658DEC0066232A /* MainMenu.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
7D17C5031D658DEC0066232A /* Base */,
|
||||
);
|
||||
name = MainMenu.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
7D24C8741D2CDEA7009932EE /* 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_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
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;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
7D24C8751D2CDEA7009932EE /* 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_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
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;
|
||||
};
|
||||
7D24C8771D2CDEA7009932EE /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "Developer ID Application";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"IS_INSTALLER_APP=1",
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
|
||||
INFOPLIST_FILE = Installer/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.objective-see.OverSightInstaller";
|
||||
PRODUCT_NAME = Installer;
|
||||
USER_HEADER_SEARCH_PATHS = ../Shared;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
7D24C8781D2CDEA7009932EE /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "Developer ID Application";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "IS_INSTALLER_APP=1";
|
||||
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
|
||||
INFOPLIST_FILE = Installer/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.objective-see.OverSightInstaller";
|
||||
PRODUCT_NAME = Installer;
|
||||
USER_HEADER_SEARCH_PATHS = ../Shared;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
7D24C8601D2CDEA7009932EE /* Build configuration list for PBXProject "Installer" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
7D24C8741D2CDEA7009932EE /* Debug */,
|
||||
7D24C8751D2CDEA7009932EE /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
7D24C8761D2CDEA7009932EE /* Build configuration list for PBXNativeTarget "Installer" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
7D24C8771D2CDEA7009932EE /* Debug */,
|
||||
7D24C8781D2CDEA7009932EE /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 7D24C85D1D2CDEA7009932EE /* Project object */;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:WhatsYourSign.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// AppDelegate.h
|
||||
// OverSight
|
||||
//
|
||||
// Created by Patrick Wardle on 9/01/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "AboutWindowController.h"
|
||||
#import "ErrorWindowController.h"
|
||||
#import "ConfigureWindowController.h"
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate, NSMenuDelegate, NSWindowDelegate>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* PROPERTIES */
|
||||
|
||||
//about window controller
|
||||
@property(nonatomic, retain)AboutWindowController* aboutWindowController;
|
||||
|
||||
//configure window controller
|
||||
@property(nonatomic, retain)ConfigureWindowController* configureWindowController;
|
||||
|
||||
//error window controller
|
||||
@property(nonatomic, retain)ErrorWindowController* errorWindowController;
|
||||
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//display configuration window w/ 'install' || 'uninstall' button
|
||||
-(void)displayConfigureWindow:(BOOL)isInstalled;
|
||||
|
||||
//display error window
|
||||
-(void)displayErrorWindow:(NSDictionary*)errorInfo;
|
||||
|
||||
@end
|
||||
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
//
|
||||
// AppDelegate.m
|
||||
// OverSight
|
||||
//
|
||||
// Created by Patrick Wardle on 9/01/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
//TODO: remove:
|
||||
// sudo lsmp -p 13513
|
||||
|
||||
#import "Consts.h"
|
||||
#import "Configure.h"
|
||||
#import "Exception.h"
|
||||
#import "Utilities.h"
|
||||
#import "AppDelegate.h"
|
||||
|
||||
@interface AppDelegate ()
|
||||
|
||||
@property (weak) IBOutlet NSWindow *window;
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
@synthesize aboutWindowController;
|
||||
@synthesize errorWindowController;
|
||||
@synthesize configureWindowController;
|
||||
|
||||
//main app interface
|
||||
-(void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
||||
{
|
||||
//config object
|
||||
Configure* configureObj = nil;
|
||||
|
||||
//first thing...
|
||||
// ->install exception handlers
|
||||
installExceptionHandlers();
|
||||
|
||||
//alloc/init Config obj
|
||||
configureObj = [[Configure alloc] init];
|
||||
|
||||
//show window
|
||||
[self displayConfigureWindow:[configureObj isInstalled]];
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
//automatically invoked when user clicks 'About/Info'
|
||||
// ->show about window
|
||||
-(IBAction)about:(id)sender
|
||||
{
|
||||
//alloc/init settings window
|
||||
if(nil == self.aboutWindowController)
|
||||
{
|
||||
//alloc/init
|
||||
aboutWindowController = [[AboutWindowController alloc] initWithWindowNibName:@"AboutWindow"];
|
||||
}
|
||||
|
||||
//center window
|
||||
[[self.aboutWindowController window] center];
|
||||
|
||||
//show it
|
||||
[self.aboutWindowController showWindow:self];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//display configuration window w/ 'install' || 'uninstall' button
|
||||
-(void)displayConfigureWindow:(BOOL)isInstalled
|
||||
{
|
||||
//alloc/init
|
||||
configureWindowController = [[ConfigureWindowController alloc] initWithWindowNibName:@"ConfigureWindowController"];
|
||||
|
||||
//display it
|
||||
// ->call this first to so that outlets are connected
|
||||
[self.configureWindowController display];
|
||||
|
||||
//configure it
|
||||
[self.configureWindowController configure:isInstalled];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//display error window
|
||||
-(void)displayErrorWindow:(NSDictionary*)errorInfo
|
||||
{
|
||||
//alloc error window
|
||||
errorWindowController = [[ErrorWindowController alloc] initWithWindowNibName:@"ErrorWindowController"];
|
||||
|
||||
//main thread
|
||||
// ->just show UI alert, unless its fatal (then load URL)
|
||||
if(YES == [NSThread isMainThread])
|
||||
{
|
||||
//non-fatal errors
|
||||
// ->show error popup
|
||||
if(YES != [errorInfo[KEY_ERROR_URL] isEqualToString:FATAL_ERROR_URL])
|
||||
{
|
||||
//display it
|
||||
// ->call this first to so that outlets are connected
|
||||
[self.errorWindowController display];
|
||||
|
||||
//configure it
|
||||
[self.errorWindowController configure:errorInfo];
|
||||
}
|
||||
//fatal error
|
||||
// ->launch browser to go to fatal error page, then exit
|
||||
else
|
||||
{
|
||||
//launch browser
|
||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:errorInfo[KEY_ERROR_URL]]];
|
||||
|
||||
//then exit
|
||||
[NSApp terminate:self];
|
||||
}
|
||||
}
|
||||
//background thread
|
||||
// ->have to show error window on main thread
|
||||
else
|
||||
{
|
||||
//show alert
|
||||
// ->in main UI thread
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
|
||||
//display it
|
||||
// ->call this first to so that outlets are connected
|
||||
[self.errorWindowController display];
|
||||
|
||||
//configure it
|
||||
[self.errorWindowController configure:errorInfo];
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,68 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "16x16",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_16x16.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "16x16",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_16x16@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "32x32",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_32x32.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "32x32",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_32x32@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "128x128",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_128x128.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "128x128",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_128x128@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "256x256",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_256x256.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "256x256",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_256x256@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "512x512",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_512x512.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "512x512",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_512x512@2x.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 105 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 105 KiB |
After Width: | Height: | Size: 246 KiB |
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
<?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>
|
||||
<deployment identifier="macosx"/>
|
||||
<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"/>
|
||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
|
||||
<items>
|
||||
<menuItem title="WhatsYourSign" id="1Xt-HY-uBw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="WhatsYourSign" systemMenu="apple" id="uQy-DD-JDr">
|
||||
<items>
|
||||
<menuItem title="About" id="5kV-Vb-QxS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="about:" target="Voe-Tx-rLC" id="Hep-HT-rEM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
|
||||
<menuItem title="Quit" keyEquivalent="q" id="4sb-4s-VLi">
|
||||
<connections>
|
||||
<action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</objects>
|
||||
</document>
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// Configure.h
|
||||
// OverSight
|
||||
//
|
||||
// Created by Patrick Wardle on 9/01/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __WYS_Configure_h
|
||||
#define __WYS_Configure_h
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface Configure : NSObject
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//determine if extension is installed
|
||||
-(BOOL)isInstalled;
|
||||
|
||||
//invokes appropriate install || uninstall logic
|
||||
-(BOOL)configure:(NSUInteger)parameter;
|
||||
|
||||
//install
|
||||
-(BOOL)install;
|
||||
|
||||
//uninstall
|
||||
-(BOOL)uninstall;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
|
@ -0,0 +1,233 @@
|
|||
//
|
||||
// Configure.m
|
||||
// OverSight
|
||||
//
|
||||
// Created by Patrick Wardle on 9/01/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "Consts.h"
|
||||
#import "Logging.h"
|
||||
#import "Utilities.h"
|
||||
#import "Configure.h"
|
||||
|
||||
|
||||
@implementation Configure
|
||||
|
||||
//invokes appropriate install || uninstall logic
|
||||
-(BOOL)configure:(NSUInteger)parameter
|
||||
{
|
||||
//return var
|
||||
BOOL wasConfigured = NO;
|
||||
|
||||
//install extension
|
||||
if(ACTION_INSTALL_FLAG == parameter)
|
||||
{
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"installing...");
|
||||
|
||||
//if already installed though
|
||||
// ->uninstall everything first
|
||||
if(YES == [self isInstalled])
|
||||
{
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"already installed, so uninstalling...");
|
||||
|
||||
//uninstall
|
||||
if(YES != [self uninstall])
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"uninstalled");
|
||||
}
|
||||
|
||||
//install
|
||||
if(YES != [self install])
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"installed!");
|
||||
}
|
||||
//uninstall extension
|
||||
else if(ACTION_UNINSTALL_FLAG == parameter)
|
||||
{
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"uninstalling...");
|
||||
|
||||
//uninstall
|
||||
if(YES != [self uninstall])
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"uninstalled!");
|
||||
}
|
||||
|
||||
//no errors
|
||||
wasConfigured = YES;
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return wasConfigured;
|
||||
}
|
||||
|
||||
//determine if installed
|
||||
// ->simply checks if extension binary exists
|
||||
-(BOOL)isInstalled
|
||||
{
|
||||
//check if extension exists
|
||||
return [[NSFileManager defaultManager] fileExistsAtPath:[[EXTENSION_FOLDER stringByExpandingTildeInPath] stringByAppendingPathComponent:EXTENSION_NAME]];
|
||||
}
|
||||
|
||||
|
||||
//install
|
||||
// a) create and copy extension to ~/Library/WhatsYourSign
|
||||
// b) add extension: 'pluginkit -a /path/2/WhatsYourSign.appex'
|
||||
// c) enable extension: 'pluginkit -e use -i com.objective-see.WhatsYourSignExt.FinderSync'
|
||||
-(BOOL)install
|
||||
{
|
||||
//return/status var
|
||||
BOOL wasInstalled = NO;
|
||||
|
||||
//error
|
||||
NSError* error = nil;
|
||||
|
||||
//path to finder sync (src)
|
||||
NSString* extensionPathSrc = nil;
|
||||
|
||||
//path to finder sync (dest)
|
||||
NSString* extensionPathDest = nil;
|
||||
|
||||
//results from 'pluginkit' cmd
|
||||
NSData* results = nil;
|
||||
|
||||
//set src path
|
||||
// ->orginally stored in installer app's /Resource bundle
|
||||
extensionPathSrc = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:EXTENSION_NAME];
|
||||
|
||||
//set dest path
|
||||
extensionPathDest = [[EXTENSION_FOLDER stringByExpandingTildeInPath] stringByAppendingPathComponent:EXTENSION_NAME];
|
||||
|
||||
//check if extension folder needs to be created
|
||||
if(YES != [[NSFileManager defaultManager] fileExistsAtPath:[EXTENSION_FOLDER stringByExpandingTildeInPath]])
|
||||
{
|
||||
//create it
|
||||
if(YES != [[NSFileManager defaultManager] createDirectoryAtPath:[EXTENSION_FOLDER stringByExpandingTildeInPath] withIntermediateDirectories:YES attributes:nil error:&error])
|
||||
{
|
||||
//err msg
|
||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to create extension's directory %@ (%@)", EXTENSION_FOLDER, error]);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
//move extension into persistent location
|
||||
// ->'/Library/WhatsYourSign/' + extension name
|
||||
if(YES != [[NSFileManager defaultManager] copyItemAtPath:extensionPathSrc toPath:extensionPathDest error:&error])
|
||||
{
|
||||
//err msg
|
||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to copy %@ -> %@ (%@)", extensionPathSrc, extensionPathDest, error]);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"copied %@ -> %@", extensionPathSrc, extensionPathDest]);
|
||||
|
||||
//install extension via 'pluginkit -a <path 2 ext>
|
||||
results = execTask(PLUGIN_KIT, @[@"-a", extensionPathDest]);
|
||||
if(0 != results.length)
|
||||
{
|
||||
//err msg
|
||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"pluginkit failed to install extension (%@)", [[NSString alloc] initWithData:results encoding:NSUTF8StringEncoding]]);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//nap
|
||||
// ->VM sometimes didn't enable
|
||||
[NSThread sleepForTimeInterval:0.5];
|
||||
|
||||
//enable extension via 'pluginkit -e use -i <ext bundle id>
|
||||
results = execTask(PLUGIN_KIT, @[@"-e", @"use", @"-i", EXTENSION_BUNDLE_ID]);
|
||||
if(0 != results.length)
|
||||
{
|
||||
//err msg
|
||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"pluginkit failed to enable extension (%@)", [[NSString alloc] initWithData:results encoding:NSUTF8StringEncoding]]);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//no error
|
||||
wasInstalled = YES;
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return wasInstalled;
|
||||
}
|
||||
|
||||
//uninstall
|
||||
// a) remove it (pluginkit -r <path 2 ext>)
|
||||
// b) delete binary & folder; /Library/WhatsYourSign
|
||||
-(BOOL)uninstall
|
||||
{
|
||||
//return/status var
|
||||
BOOL wasUninstalled = NO;
|
||||
|
||||
//status var
|
||||
// ->since want to try all uninstall steps, but record if any fail
|
||||
BOOL bAnyErrors = NO;
|
||||
|
||||
//path to finder sync
|
||||
NSString* extensionPath = nil;
|
||||
|
||||
//error
|
||||
NSError* error = nil;
|
||||
|
||||
//init path
|
||||
extensionPath = [[EXTENSION_FOLDER stringByExpandingTildeInPath] stringByAppendingPathComponent:EXTENSION_NAME];
|
||||
|
||||
//this always seem to 'fail' with 'remove: no plugin at <path/2/FinderSync.appex>'
|
||||
// ->but yet works, so just ignore any return from this invocation of execTask()
|
||||
execTask(PLUGIN_KIT, @[@"-r", extensionPath]);
|
||||
|
||||
//delete folder
|
||||
if(YES != [[NSFileManager defaultManager] removeItemAtPath:[EXTENSION_FOLDER stringByExpandingTildeInPath] error:&error])
|
||||
{
|
||||
//err msg
|
||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to delete extension directory %@ (%@)", EXTENSION_FOLDER, error]);
|
||||
|
||||
//set flag
|
||||
bAnyErrors = YES;
|
||||
|
||||
//keep uninstalling...
|
||||
}
|
||||
|
||||
//only success when there were no errors
|
||||
if(YES != bAnyErrors)
|
||||
{
|
||||
//happy
|
||||
wasUninstalled = YES;
|
||||
}
|
||||
|
||||
return wasUninstalled;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// ConfigureWindowController.h
|
||||
// OverSight
|
||||
//
|
||||
// Created by Patrick Wardle on 9/01/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface ConfigureWindowController : NSWindowController <NSWindowDelegate>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* PROPERTIES */
|
||||
|
||||
@property (weak) IBOutlet NSProgressIndicator *activityIndicator;
|
||||
@property (weak) IBOutlet NSTextField *statusMsg;
|
||||
@property (weak) IBOutlet NSButton *installButton;
|
||||
@property (weak) IBOutlet NSButton *uninstallButton;
|
||||
@property (weak) IBOutlet NSButton *moreInfoButton;
|
||||
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//install/uninstall button handler
|
||||
-(IBAction)buttonHandler:(id)sender;
|
||||
|
||||
//(more) info button handler
|
||||
-(IBAction)info:(id)sender;
|
||||
|
||||
//configure window/buttons
|
||||
// ->also brings to front
|
||||
-(void)configure:(BOOL)isInstalled;
|
||||
|
||||
//display (show) window
|
||||
-(void)display;
|
||||
|
||||
@end
|
|
@ -0,0 +1,406 @@
|
|||
//
|
||||
// ConfigureWindowController.m
|
||||
// OverSight
|
||||
//
|
||||
// Created by Patrick Wardle on 9/01/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Consts.h"
|
||||
#import "Configure.h"
|
||||
#import "Utilities.h"
|
||||
#import "ConfigureWindowController.h"
|
||||
|
||||
@implementation ConfigureWindowController
|
||||
|
||||
@synthesize statusMsg;
|
||||
@synthesize moreInfoButton;
|
||||
|
||||
//automatically called when nib is loaded
|
||||
// ->just center window
|
||||
-(void)awakeFromNib
|
||||
{
|
||||
//center
|
||||
[self.window center];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//configure window/buttons
|
||||
// ->also brings window to front
|
||||
-(void)configure:(BOOL)isInstalled
|
||||
{
|
||||
//set window title
|
||||
[self window].title = [NSString stringWithFormat:@"version %@", getAppVersion()];
|
||||
|
||||
//yosemite doesn't support emojis :P
|
||||
if(getVersion(gestaltSystemVersionMinor) <= OS_MINOR_VERSION_YOSEMITE)
|
||||
{
|
||||
//init status msg
|
||||
[self.statusMsg setStringValue:@"monitor audio & video access"];
|
||||
}
|
||||
//el capitan supports emojis
|
||||
else
|
||||
{
|
||||
//init status msg
|
||||
[self.statusMsg setStringValue:@"monitor 🎤 and 📸 access"];
|
||||
}
|
||||
|
||||
//enable 'uninstall' button when app is installed already
|
||||
if(YES == isInstalled)
|
||||
{
|
||||
//enable
|
||||
self.uninstallButton.enabled = YES;
|
||||
}
|
||||
//otherwise disable
|
||||
else
|
||||
{
|
||||
//disable
|
||||
self.uninstallButton.enabled = NO;
|
||||
}
|
||||
|
||||
//make 'install' have focus
|
||||
// ->more likely they'll be upgrading, but do after a delay so it sticks...
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.25 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
|
||||
|
||||
//set responder
|
||||
[self.window makeFirstResponder:self.installButton];
|
||||
|
||||
});
|
||||
|
||||
//set delegate
|
||||
[self.window setDelegate:self];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//display (show) window
|
||||
// ->center, make front, set bg to white, etc
|
||||
-(void)display
|
||||
{
|
||||
//center window
|
||||
[[self window] center];
|
||||
|
||||
//show (now configured) windows
|
||||
[self showWindow:self];
|
||||
|
||||
//make it key window
|
||||
[self.window makeKeyAndOrderFront:self];
|
||||
|
||||
//make window front
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
|
||||
//make white
|
||||
[self.window setBackgroundColor: NSColor.whiteColor];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//button handler for uninstall/install
|
||||
-(IBAction)buttonHandler:(id)sender
|
||||
{
|
||||
//button title
|
||||
NSString* buttonTitle = nil;
|
||||
|
||||
//extact button title
|
||||
buttonTitle = ((NSButton*)sender).title;
|
||||
|
||||
//action
|
||||
NSUInteger action = 0;
|
||||
|
||||
//hide 'get more info' button
|
||||
self.moreInfoButton.hidden = YES;
|
||||
|
||||
//set action
|
||||
// ->install daemon
|
||||
if(YES == [buttonTitle isEqualToString:ACTION_INSTALL])
|
||||
{
|
||||
//set
|
||||
action = ACTION_INSTALL_FLAG;
|
||||
}
|
||||
//set action
|
||||
// ->uninstall daemon
|
||||
else
|
||||
{
|
||||
//set
|
||||
action = ACTION_UNINSTALL_FLAG;
|
||||
}
|
||||
|
||||
//disable 'x' button
|
||||
// ->don't want user killing app during install/upgrade
|
||||
[[self.window standardWindowButton:NSWindowCloseButton] setEnabled:NO];
|
||||
|
||||
//clear status msg
|
||||
[self.statusMsg setStringValue:@""];
|
||||
|
||||
//force redraw of status msg
|
||||
// ->sometime doesn't refresh (e.g. slow VM)
|
||||
[self.statusMsg setNeedsDisplay:YES];
|
||||
|
||||
//invoke logic to install/uninstall
|
||||
// ->do in background so UI doesn't block
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
|
||||
^{
|
||||
//install/uninstall
|
||||
[self lifeCycleEvent:action];
|
||||
|
||||
});
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//button handler for '?' button (on an error)
|
||||
// ->load objective-see's documentation for error(s) in default browser
|
||||
-(IBAction)info:(id)sender
|
||||
{
|
||||
//url
|
||||
NSURL *helpURL = nil;
|
||||
|
||||
//build help URL
|
||||
helpURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@#errors", PRODUCT_URL]];
|
||||
|
||||
//open URL
|
||||
// ->invokes user's default browser
|
||||
[[NSWorkspace sharedWorkspace] openURL:helpURL];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//perform install | uninstall via Control obj
|
||||
// ->invoked on background thread so that UI doesn't block
|
||||
-(void)lifeCycleEvent:(NSUInteger)event
|
||||
{
|
||||
//status var
|
||||
BOOL status = NO;
|
||||
|
||||
//configure object
|
||||
Configure* configureObj = nil;
|
||||
|
||||
//dbg msg
|
||||
//logMsg(LOG_DEBUG, [NSString stringWithFormat:@"handling life cycle event, %lu", (unsigned long)event]);
|
||||
|
||||
//alloc control object
|
||||
configureObj = [[Configure alloc] init];
|
||||
|
||||
//begin event
|
||||
// ->updates ui on main thread
|
||||
dispatch_sync(dispatch_get_main_queue(),
|
||||
^{
|
||||
//complete
|
||||
[self beginEvent:event];
|
||||
});
|
||||
|
||||
//sleep
|
||||
// ->allow 'install' || 'uninstall' msg to show up
|
||||
sleep(1);
|
||||
|
||||
//perform action (install | uninstall)
|
||||
// ->perform background actions
|
||||
if(YES == [configureObj configure:event])
|
||||
{
|
||||
//set flag
|
||||
status = YES;
|
||||
}
|
||||
|
||||
//error occurred
|
||||
else
|
||||
{
|
||||
//err msg
|
||||
//logMsg(LOG_ERR, @"ERROR: failed to perform life cycle event");
|
||||
|
||||
//set flag
|
||||
status = NO;
|
||||
}
|
||||
|
||||
//complet event
|
||||
// ->updates ui on main thread
|
||||
dispatch_async(dispatch_get_main_queue(),
|
||||
^{
|
||||
//complete
|
||||
[self completeEvent:status event:event];
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//begin event
|
||||
// ->basically just update UI
|
||||
-(void)beginEvent:(NSUInteger)event
|
||||
{
|
||||
//status msg frame
|
||||
CGRect statusMsgFrame = {0};
|
||||
|
||||
//grab exiting frame
|
||||
statusMsgFrame = self.statusMsg.frame;
|
||||
|
||||
//avoid activity indicator
|
||||
// ->shift frame shift delta
|
||||
statusMsgFrame.origin.x += FRAME_SHIFT;
|
||||
|
||||
//update frame to align
|
||||
self.statusMsg.frame = statusMsgFrame;
|
||||
|
||||
//align text left
|
||||
[self.statusMsg setAlignment:NSLeftTextAlignment];
|
||||
|
||||
//install msg
|
||||
if(ACTION_INSTALL_FLAG == event)
|
||||
{
|
||||
//update status msg
|
||||
[self.statusMsg setStringValue:@"Installing..."];
|
||||
}
|
||||
//uninstall msg
|
||||
else
|
||||
{
|
||||
//update status msg
|
||||
[self.statusMsg setStringValue:@"Uninstalling..."];
|
||||
}
|
||||
|
||||
//disable action button
|
||||
self.uninstallButton.enabled = NO;
|
||||
|
||||
//disable cancel button
|
||||
self.installButton.enabled = NO;
|
||||
|
||||
//show spinner
|
||||
[self.activityIndicator setHidden:NO];
|
||||
|
||||
//start spinner
|
||||
[self.activityIndicator startAnimation:nil];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//complete event
|
||||
// ->update UI after background event has finished
|
||||
-(void)completeEvent:(BOOL)success event:(NSUInteger)event
|
||||
{
|
||||
//status msg frame
|
||||
CGRect statusMsgFrame = {0};
|
||||
|
||||
//action
|
||||
NSString* action = nil;
|
||||
|
||||
//result msg
|
||||
NSMutableString* resultMsg = nil;
|
||||
|
||||
//msg font
|
||||
NSColor* resultMsgColor = nil;
|
||||
|
||||
//generally want centered text
|
||||
[self.statusMsg setAlignment:NSCenterTextAlignment];
|
||||
|
||||
//set action msg for install
|
||||
if(ACTION_INSTALL_FLAG == event)
|
||||
{
|
||||
//set msg
|
||||
action = @"install";
|
||||
}
|
||||
//set action msg for uninstall
|
||||
else
|
||||
{
|
||||
//set msg
|
||||
action = @"uninstall";
|
||||
}
|
||||
|
||||
//success
|
||||
if(YES == success)
|
||||
{
|
||||
//set result msg
|
||||
resultMsg = [NSMutableString stringWithFormat:@"WhatsYourSign %@ed!", action];
|
||||
|
||||
//add extra info when installed
|
||||
if(ACTION_INSTALL_FLAG == event)
|
||||
{
|
||||
//append
|
||||
[resultMsg appendString:@"\nany file: ctl+click->'Signing Info'"];
|
||||
}
|
||||
|
||||
//set font to black
|
||||
resultMsgColor = [NSColor blackColor];
|
||||
}
|
||||
//failure
|
||||
else
|
||||
{
|
||||
//set result msg
|
||||
resultMsg = [NSMutableString stringWithFormat:@"error: %@ failed", action];
|
||||
|
||||
//set font to red
|
||||
resultMsgColor = [NSColor redColor];
|
||||
|
||||
//show 'get more info' button
|
||||
self.moreInfoButton.hidden = NO;
|
||||
}
|
||||
|
||||
//stop/hide spinner
|
||||
[self.activityIndicator stopAnimation:nil];
|
||||
|
||||
//hide spinner
|
||||
[self.activityIndicator setHidden:YES];
|
||||
|
||||
//grab exiting frame
|
||||
statusMsgFrame = self.statusMsg.frame;
|
||||
|
||||
//shift back since activity indicator is gone
|
||||
statusMsgFrame.origin.x -= FRAME_SHIFT;
|
||||
|
||||
//update frame to align
|
||||
self.statusMsg.frame = statusMsgFrame;
|
||||
|
||||
//set font to bold
|
||||
[self.statusMsg setFont:[NSFont fontWithName:@"Menlo-Bold" size:13]];
|
||||
|
||||
//set msg color
|
||||
[self.statusMsg setTextColor:resultMsgColor];
|
||||
|
||||
//set status msg
|
||||
[self.statusMsg setStringValue:resultMsg];
|
||||
|
||||
//toggle buttons
|
||||
// ->after install turn on 'uninstall' and off 'install'
|
||||
if(ACTION_INSTALL_FLAG == event)
|
||||
{
|
||||
//enable uninstall
|
||||
self.uninstallButton.enabled = YES;
|
||||
|
||||
//disable install
|
||||
self.installButton.enabled = NO;
|
||||
}
|
||||
//toggle buttons
|
||||
// ->after uninstall turn off 'uninstall' and on 'install'
|
||||
else
|
||||
{
|
||||
//disable
|
||||
self.uninstallButton.enabled = NO;
|
||||
|
||||
//enable close button
|
||||
self.installButton.enabled = YES;
|
||||
}
|
||||
|
||||
//ok to re-enable 'x' button
|
||||
[[self.window standardWindowButton:NSWindowCloseButton] setEnabled:YES];
|
||||
|
||||
//(re)make window window key
|
||||
[self.window makeKeyAndOrderFront:self];
|
||||
|
||||
//(re)make window front
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//automatically invoked when window is closing
|
||||
// ->just exit application
|
||||
-(void)windowWillClose:(NSNotification *)notification
|
||||
{
|
||||
//exit
|
||||
[NSApp terminate:self];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@end
|
|
@ -0,0 +1,89 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="15G31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="ConfigureWindowController">
|
||||
<connections>
|
||||
<outlet property="activityIndicator" destination="b1w-5W-ayX" id="P5e-PO-Ozi"/>
|
||||
<outlet property="installButton" destination="553-2y-kvm" id="nxf-wO-EI3"/>
|
||||
<outlet property="moreInfoButton" destination="QWu-qZ-Za2" id="8kC-Ga-5oJ"/>
|
||||
<outlet property="statusMsg" destination="SpB-Xc-WlB" id="jlm-ke-XfM"/>
|
||||
<outlet property="uninstallButton" destination="XrB-7g-xya" id="0Hc-Xn-STu"/>
|
||||
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="F0z-JX-Cv5">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" texturedBackground="YES" unifiedTitleAndToolbar="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="196" y="240" width="460" height="176"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
|
||||
<view key="contentView" id="se5-gp-TjO">
|
||||
<rect key="frame" x="0.0" y="0.0" width="460" height="176"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<progressIndicator hidden="YES" wantsLayer="YES" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" maxValue="100" bezeled="NO" indeterminate="YES" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="b1w-5W-ayX">
|
||||
<rect key="frame" x="144" y="31" width="32" height="32"/>
|
||||
</progressIndicator>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="XrB-7g-xya">
|
||||
<rect key="frame" x="138" y="76" width="115" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Uninstall" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="G7H-Q1-04P">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="buttonHandler:" target="-2" id="GAh-S3-3e6"/>
|
||||
</connections>
|
||||
</button>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fgM-lv-GeJ">
|
||||
<rect key="frame" x="13" y="43" width="114" height="123"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="icon" id="bCU-0f-ff8"/>
|
||||
</imageView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="293" translatesAutoresizingMaskIntoConstraints="NO" id="SpB-Xc-WlB">
|
||||
<rect key="frame" x="142" y="10" width="297" height="47"/>
|
||||
<textFieldCell key="cell" truncatesLastVisibleLine="YES" enabled="NO" sendsActionOnEndEditing="YES" alignment="center" id="Rib-WU-Syl">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="553-2y-kvm">
|
||||
<rect key="frame" x="331" y="76" width="115" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Install" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="1hy-8F-qxt">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="buttonHandler:" target="-2" id="1wC-Ls-D2F"/>
|
||||
</connections>
|
||||
</button>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="K52-9g-sjn">
|
||||
<rect key="frame" x="138" y="109" width="243" height="67"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="overSight" id="WRg-I2-vkK"/>
|
||||
</imageView>
|
||||
<button hidden="YES" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="QWu-qZ-Za2">
|
||||
<rect key="frame" x="414" y="33" width="25" height="25"/>
|
||||
<buttonCell key="cell" type="help" bezelStyle="helpButton" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="v1Z-aX-Wlm">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="info:" target="-2" id="tg3-SV-AH9"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="185" y="-256"/>
|
||||
</window>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="icon" width="512" height="512"/>
|
||||
<image name="overSight" width="1396" height="286"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// ErrorWindowController.h
|
||||
// OverSight
|
||||
//
|
||||
// Created by Patrick Wardle on 7/15/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface ErrorWindowController : NSWindowController <NSWindowDelegate>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//main msg in window
|
||||
@property (weak) IBOutlet NSTextField *errMsg;
|
||||
|
||||
//sub msg in window
|
||||
@property (weak) IBOutlet NSTextField *errSubMsg;
|
||||
|
||||
//info/help/fix button
|
||||
@property (weak) IBOutlet NSButton *infoButton;
|
||||
|
||||
//close button
|
||||
@property (weak) IBOutlet NSButton *closeButton;
|
||||
|
||||
//(optional) url for 'Info' button
|
||||
@property(nonatomic, retain) NSURL* errorURL;
|
||||
|
||||
//flag indicating close button should exit app
|
||||
@property BOOL shouldExit;
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//configure the object/window
|
||||
-(void)configure:(NSDictionary*)errorInfo;
|
||||
|
||||
//display (show) window
|
||||
-(void)display;
|
||||
|
||||
@end
|
|
@ -0,0 +1,150 @@
|
|||
//
|
||||
// ErrorWindowController.m
|
||||
// OverSight
|
||||
//
|
||||
// Created by Patrick Wardle on 7/15/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Consts.h"
|
||||
#import "ErrorWindowController.h"
|
||||
|
||||
@interface ErrorWindowController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation ErrorWindowController
|
||||
|
||||
@synthesize errorURL;
|
||||
@synthesize shouldExit;
|
||||
@synthesize closeButton;
|
||||
|
||||
//automatically called when nib is loaded
|
||||
// ->center window
|
||||
-(void)awakeFromNib
|
||||
{
|
||||
//center
|
||||
[self.window center];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//configure the object/window
|
||||
-(void)configure:(NSDictionary*)errorInfo
|
||||
{
|
||||
//set error msg
|
||||
self.errMsg.stringValue = errorInfo[KEY_ERROR_MSG];
|
||||
|
||||
//set error sub msg
|
||||
self.errSubMsg.stringValue = errorInfo[KEY_ERROR_SUB_MSG];
|
||||
|
||||
//save exit
|
||||
self.shouldExit = [errorInfo[KEY_ERROR_SHOULD_EXIT] boolValue];
|
||||
|
||||
//grab optional error url
|
||||
if(nil != errorInfo[KEY_ERROR_URL])
|
||||
{
|
||||
//extract/convert
|
||||
self.errorURL = [NSURL URLWithString:errorInfo[KEY_ERROR_URL]];
|
||||
}
|
||||
|
||||
//when exiting
|
||||
// ->change 'close' to 'exit'
|
||||
if(YES == self.shouldExit)
|
||||
{
|
||||
//change title
|
||||
self.closeButton.title = @"Exit";
|
||||
}
|
||||
|
||||
//for fatal errors
|
||||
// ->change 'Info' to 'help fix'
|
||||
if(YES == [[self.errorURL absoluteString] isEqualToString:FATAL_ERROR_URL])
|
||||
{
|
||||
//change title
|
||||
self.infoButton.title = @"Help Fix";
|
||||
}
|
||||
|
||||
//set delegate
|
||||
[self.window setDelegate:self];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//display (show) window
|
||||
-(void)display
|
||||
{
|
||||
//show (now configured), alert
|
||||
[self showWindow:self];
|
||||
|
||||
//make it key window
|
||||
[self.window makeKeyAndOrderFront:self];
|
||||
|
||||
//make window front
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
|
||||
//make 'close' have focus
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.25 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
|
||||
|
||||
//make close button active
|
||||
[self.window makeFirstResponder:closeButton];
|
||||
|
||||
});
|
||||
|
||||
//make white
|
||||
[self.window setBackgroundColor: NSColor.whiteColor];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//invoked when user clicks '?' (help button)
|
||||
// ->open url with more info about the error(s)
|
||||
-(IBAction)help:(id)sender
|
||||
{
|
||||
//if a url was specified
|
||||
// ->use that one
|
||||
if(nil != self.errorURL)
|
||||
{
|
||||
//open URL
|
||||
// ->invokes user's default browser
|
||||
[[NSWorkspace sharedWorkspace] openURL:self.errorURL];
|
||||
}
|
||||
//use default URL
|
||||
else
|
||||
{
|
||||
//open URL
|
||||
// ->invokes user's default browser
|
||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:ERRORS_URL]];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//invoked when user clicks 'close'
|
||||
// ->just close window
|
||||
-(IBAction)close:(id)sender
|
||||
{
|
||||
//close
|
||||
[self.window close];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//automatically invoked when window is closing
|
||||
// ->exit the app if specified...
|
||||
-(void)windowWillClose:(NSNotification *)notification
|
||||
{
|
||||
//check if should exit process
|
||||
// ->e.g. an error during install, etc
|
||||
if(YES == self.shouldExit)
|
||||
{
|
||||
//dbg msg
|
||||
//logMsg(LOG_DEBUG, @"exiting application");
|
||||
|
||||
//exit
|
||||
[NSApp terminate:self];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,78 @@
|
|||
<?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">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10116"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="ErrorWindowController">
|
||||
<connections>
|
||||
<outlet property="closeButton" destination="zbs-ul-WTJ" id="1fu-zv-brA"/>
|
||||
<outlet property="errMsg" destination="Act-U9-8G9" id="PMa-6M-gwu"/>
|
||||
<outlet property="errSubMsg" destination="tQ0-f2-G4C" id="4hz-9M-Gub"/>
|
||||
<outlet property="infoButton" destination="sNV-Jw-9dZ" id="qdf-xQ-ubf"/>
|
||||
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window title="WHATSYOURSIGN? Error" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" texturedBackground="YES" unifiedTitleAndToolbar="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="744" y="427" width="380" height="137"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
|
||||
<view key="contentView" id="se5-gp-TjO">
|
||||
<rect key="frame" x="0.0" y="0.0" width="380" height="137"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zbs-ul-WTJ">
|
||||
<rect key="frame" x="284" y="13" width="82" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Close" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Pjp-Se-SfK">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="close:" target="-2" id="sez-MW-4AE"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="0.0" translatesAutoresizingMaskIntoConstraints="NO" id="tQ0-f2-G4C">
|
||||
<rect key="frame" x="114" y="49" width="248" height="36"/>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" title="Label" id="sk0-EF-ZfG">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="0.0" translatesAutoresizingMaskIntoConstraints="NO" id="Act-U9-8G9">
|
||||
<rect key="frame" x="114" y="88" width="248" height="20"/>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="ERROR msg" id="VCu-zh-Vcs">
|
||||
<font key="font" size="13" name="Menlo-Bold"/>
|
||||
<color key="textColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="sNV-Jw-9dZ">
|
||||
<rect key="frame" x="202" y="13" width="82" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Info" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="L1w-RB-EC4">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="help:" target="-2" id="gCm-No-dHq"/>
|
||||
</connections>
|
||||
</button>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="sRj-I0-15e">
|
||||
<rect key="frame" x="12" y="35" width="92" height="92"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="icon" id="9iG-ot-b7i"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="257" y="269.5"/>
|
||||
</window>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="icon" width="512" height="512"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -0,0 +1,34 @@
|
|||
<?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></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.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.0</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright (c) 2016 Objective-See. All rights reserved.</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,13 @@
|
|||
//
|
||||
// main.m
|
||||
// OverSight
|
||||
//
|
||||
// Created by Patrick Wardle on 7/15/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
return NSApplicationMain(argc, argv);
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
//
|
||||
// ProcessMonitor.h
|
||||
// OverSight
|
||||
//
|
||||
// Created by Patrick Wardle on 9/01/16.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import <CoreAudio/CoreAudio.h>
|
||||
#import <CoreMedia/CoreMedia.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreMediaIO/CMIOHardware.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
|
||||
/* DEFINES */
|
||||
|
||||
#define VIDEO_DISABLED 0x0
|
||||
#define VIDEO_ENABLED 0x1
|
||||
|
||||
#define EVENT_SOURCE @"source"
|
||||
#define EVENT_DEVICE @"device"
|
||||
#define EVENT_DEVICE_STATUS @"status"
|
||||
#define EVENT_PROCESS_ID @"processID"
|
||||
|
||||
#define SOURCE_AUDIO @0x1
|
||||
#define SOURCE_VIDEO @0x2
|
||||
|
||||
#define DEVICE_INACTIVE @0x0
|
||||
#define DEVICE_ACTIVE @0x1
|
||||
|
||||
@interface AVMonitor : NSObject <NSUserNotificationCenterDelegate>
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* PROPERTIES */
|
||||
|
||||
//apple mic (AVCaptureHALDevice)
|
||||
@property(nonatomic, retain)AVCaptureDevice* mic;
|
||||
|
||||
//apple camera (AVCaptureDALDevice)
|
||||
@property(nonatomic, retain)AVCaptureDevice* camera;
|
||||
|
||||
//flag indicating audio (mic) is active
|
||||
@property BOOL audioActive;
|
||||
|
||||
//flag indicating video (camera) is active
|
||||
@property BOOL videoActive;
|
||||
|
||||
//monitor thread
|
||||
@property(nonatomic, retain)NSThread* videoMonitorThread;
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//kicks off thread to monitor
|
||||
-(BOOL)monitor;
|
||||
|
||||
//monitor for new procs
|
||||
-(void)monitor4Procs;
|
||||
|
||||
//determine if audio is active
|
||||
-(void)setAudioDevStatus:(AudioObjectID)deviceID;
|
||||
|
||||
//determine if video is active
|
||||
-(void)setVideoDevStatus:(CMIOObjectID)deviceID;
|
||||
|
||||
@end
|
|
@ -0,0 +1,941 @@
|
|||
//
|
||||
// AVMonitor.m
|
||||
// OverSight
|
||||
//
|
||||
// Created by Patrick Wardle on 9/01/16.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
//TODO: NSLOg -> logmSg
|
||||
|
||||
#import "Consts.h"
|
||||
#import "Logging.h"
|
||||
#import "Utilities.h"
|
||||
#import "AVMonitor.h"
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import "../Shared/XPCProtocol.h"
|
||||
|
||||
//TODO: make instance methods?!
|
||||
|
||||
//grab first apple camera
|
||||
AVCaptureDevice* findAppleCamera()
|
||||
{
|
||||
//apple camera
|
||||
// ->likely FaceTime camera
|
||||
AVCaptureDevice* appleCamera = nil;
|
||||
|
||||
//list of cameras
|
||||
NSArray *cameras = nil;
|
||||
|
||||
//get cameras
|
||||
cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
|
||||
for(AVCaptureDevice* camera in cameras)
|
||||
{
|
||||
//check if apple
|
||||
if(YES == [camera.manufacturer isEqualToString:@"Apple Inc."])
|
||||
{
|
||||
//save
|
||||
appleCamera = camera;
|
||||
|
||||
//exit loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return appleCamera;
|
||||
}
|
||||
|
||||
//grab built-in mic
|
||||
AVCaptureDevice* findAppleMic()
|
||||
{
|
||||
//built-in mic
|
||||
AVCaptureDevice* appleMic = nil;
|
||||
|
||||
//list of mics
|
||||
NSArray *mics = nil;
|
||||
|
||||
//get mics
|
||||
mics = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio];
|
||||
for(AVCaptureDevice* mic in mics)
|
||||
{
|
||||
//check if apple
|
||||
// ->also check input source
|
||||
if( (YES == [mic.manufacturer isEqualToString:@"Apple Inc."]) &&
|
||||
(YES == [[[mic activeInputSource] inputSourceID] isEqualToString:@"imic"]) )
|
||||
{
|
||||
//save
|
||||
appleMic = mic;
|
||||
|
||||
//exit loop
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return appleMic;
|
||||
}
|
||||
|
||||
|
||||
@implementation AVMonitor
|
||||
|
||||
@synthesize mic;
|
||||
@synthesize camera;
|
||||
@synthesize audioActive;
|
||||
@synthesize videoActive;
|
||||
@synthesize videoMonitorThread;
|
||||
|
||||
//init
|
||||
-(id)init
|
||||
{
|
||||
//init super
|
||||
self = [super init];
|
||||
if(nil != self)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
//initialiaze AV notifcations/callbacks
|
||||
-(BOOL)monitor
|
||||
{
|
||||
//return var
|
||||
BOOL bRet = NO;
|
||||
|
||||
//xpc connection
|
||||
__block NSXPCConnection* xpcConnection = nil;
|
||||
|
||||
//device's connection id
|
||||
unsigned int connectionID = 0;
|
||||
|
||||
//selector for getting device id
|
||||
SEL methodSelector = nil;
|
||||
|
||||
//array for devices + status
|
||||
NSMutableArray* devices = nil;
|
||||
|
||||
//wait semaphore
|
||||
dispatch_semaphore_t waitSema = nil;
|
||||
|
||||
//alloc XPC connection
|
||||
xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.objective-see.OverSightXPC"];
|
||||
|
||||
//alloc device array
|
||||
devices = [NSMutableArray array];
|
||||
|
||||
//set remote object interface
|
||||
xpcConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(XPCProtocol)];
|
||||
|
||||
//resume
|
||||
[xpcConnection resume];
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"telling XPC service to begin base-lining mach messages");
|
||||
|
||||
//init wait semaphore
|
||||
waitSema = dispatch_semaphore_create(0);
|
||||
|
||||
//XPC service to begin baselining mach messages
|
||||
// ->wait, since want this to compelete before doing other things!
|
||||
[[xpcConnection remoteObjectProxy] initialize:^
|
||||
{
|
||||
|
||||
//signal sema
|
||||
dispatch_semaphore_signal(waitSema);
|
||||
|
||||
}];
|
||||
|
||||
//wait until XPC is done
|
||||
// ->XPC reply block will signal semaphore
|
||||
dispatch_semaphore_wait(waitSema, DISPATCH_TIME_FOREVER);
|
||||
|
||||
//init selector
|
||||
methodSelector = NSSelectorFromString(@"connectionID");
|
||||
|
||||
//find (first) apple camera
|
||||
self.camera = findAppleCamera();
|
||||
|
||||
//find built in mic
|
||||
self.mic = findAppleMic();
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found mic: %@", self.mic]);
|
||||
|
||||
//got camera
|
||||
// ->grab connection ID and invoke helper functions
|
||||
if( (nil != self.camera) &&
|
||||
(YES == [self.camera respondsToSelector:methodSelector]) )
|
||||
{
|
||||
//ignore leak warning
|
||||
// ->we know what we're doing via this 'performSelector'
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
||||
|
||||
//grab connection ID
|
||||
connectionID = (unsigned int)[self.camera performSelector:methodSelector withObject:nil];
|
||||
|
||||
//restore
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
//set status
|
||||
// ->will set 'videoActive' iVar
|
||||
[self setVideoDevStatus:connectionID];
|
||||
|
||||
//if video is already active
|
||||
// ->start monitoring thread
|
||||
if(YES == self.videoActive)
|
||||
{
|
||||
//tell XPC video is active
|
||||
[[xpcConnection remoteObjectProxy] updateVideoStatus:self.videoActive reply:^{
|
||||
|
||||
//signal sema
|
||||
dispatch_semaphore_signal(waitSema);
|
||||
|
||||
}];
|
||||
|
||||
//wait until XPC is done
|
||||
// ->XPC reply block will signal semaphore
|
||||
dispatch_semaphore_wait(waitSema, DISPATCH_TIME_FOREVER);
|
||||
|
||||
//alloc
|
||||
videoMonitorThread = [[NSThread alloc] initWithTarget:self selector:@selector(monitor4Procs) object:nil];
|
||||
|
||||
//start
|
||||
[self.videoMonitorThread start];
|
||||
}
|
||||
|
||||
//save camera/status into device array
|
||||
[devices addObject:@{EVENT_DEVICE:self.camera, EVENT_DEVICE_STATUS:@(self.videoActive)}];
|
||||
|
||||
//register for video events
|
||||
if(YES != [self watchVideo:connectionID])
|
||||
{
|
||||
//err msg
|
||||
}
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"registerd for video events");
|
||||
}
|
||||
//err msg
|
||||
else
|
||||
{
|
||||
//err msg
|
||||
logMsg(LOG_ERR, @"failed to find (apple) camera :(");
|
||||
}
|
||||
|
||||
//watch mic
|
||||
// ->grab connection ID and invoke helper function
|
||||
if( (nil != self.mic) &&
|
||||
(YES == [self.mic respondsToSelector:methodSelector]) )
|
||||
{
|
||||
//ignore leak warning
|
||||
// ->we know what we're doing via this 'performSelector'
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
||||
|
||||
//grab connection ID
|
||||
connectionID = (unsigned int)[self.mic performSelector:NSSelectorFromString(@"connectionID") withObject:nil];
|
||||
|
||||
//restore
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
//save camera/status into device array
|
||||
[devices addObject:@{EVENT_DEVICE:self.mic, EVENT_DEVICE_STATUS:@(self.audioActive)}];
|
||||
|
||||
//register for audio events
|
||||
if(YES != [self watchAudio:connectionID])
|
||||
{
|
||||
//err msg
|
||||
}
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"registerd for audio events");
|
||||
}
|
||||
|
||||
//err msg
|
||||
else
|
||||
{
|
||||
//err msg
|
||||
logMsg(LOG_ERR, @"failed to find (apple) mic :(");
|
||||
}
|
||||
|
||||
//send msg to status menu
|
||||
// ->update menu to show devices & their status
|
||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]).statusBarMenuController updateStatusItemMenu:devices];
|
||||
|
||||
//no errors
|
||||
bRet = YES;
|
||||
|
||||
//TODO: not needed?
|
||||
//bail
|
||||
bail:
|
||||
|
||||
//cleanup XPC
|
||||
if(nil != xpcConnection)
|
||||
{
|
||||
//close connection
|
||||
[xpcConnection invalidate];
|
||||
|
||||
//nil out
|
||||
xpcConnection = nil;
|
||||
}
|
||||
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
//determine if video is active
|
||||
// ->sets 'videoActive' iVar
|
||||
-(void)setVideoDevStatus:(CMIODeviceID)deviceID
|
||||
{
|
||||
//status var
|
||||
OSStatus status = -1;
|
||||
|
||||
//running flag
|
||||
UInt32 isRunning = -1;
|
||||
|
||||
//size of query flag
|
||||
UInt32 propertySize = 0;
|
||||
|
||||
//property address struct
|
||||
CMIOObjectPropertyAddress propertyStruct = {0};
|
||||
|
||||
//init size
|
||||
propertySize = sizeof(isRunning);
|
||||
|
||||
//init property struct's selector
|
||||
propertyStruct.mSelector = kAudioDevicePropertyDeviceIsRunningSomewhere;
|
||||
|
||||
//init property struct's scope
|
||||
propertyStruct.mScope = kCMIOObjectPropertyScopeGlobal;
|
||||
|
||||
//init property struct's element
|
||||
propertyStruct.mElement = 0;
|
||||
|
||||
//query to get 'kAudioDevicePropertyDeviceIsRunningSomewhere' status
|
||||
status = CMIOObjectGetPropertyData(deviceID, &propertyStruct, 0, NULL, sizeof(kAudioDevicePropertyDeviceIsRunningSomewhere), &propertySize, &isRunning);
|
||||
if(noErr != status)
|
||||
{
|
||||
//err msg
|
||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"getting status of video device failed with %d", status]);
|
||||
|
||||
//set error
|
||||
isRunning = -1;
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//set iVar
|
||||
self.videoActive = isRunning;
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//helper function
|
||||
// ->determines if video went active/inactive then invokes notification generator method
|
||||
-(void)handleVideoNotification:(CMIOObjectID)deviceID addresses:(const CMIOObjectPropertyAddress[]) addresses
|
||||
{
|
||||
//event dictionary
|
||||
NSMutableDictionary* event = nil;
|
||||
|
||||
//xpc connection
|
||||
__block NSXPCConnection* xpcConnection = nil;
|
||||
|
||||
//wait semaphore
|
||||
dispatch_semaphore_t waitSema = nil;
|
||||
|
||||
//init dictionary
|
||||
event = [NSMutableDictionary dictionary];
|
||||
|
||||
//sync?
|
||||
//TODO: is this a good idea?
|
||||
@synchronized (self)
|
||||
{
|
||||
|
||||
//set status
|
||||
[self setVideoDevStatus:deviceID];
|
||||
|
||||
//send msg to status menu
|
||||
// ->update menu to show (all) devices & their status
|
||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]).statusBarMenuController updateStatusItemMenu:@[@{EVENT_DEVICE:self.camera, EVENT_DEVICE_STATUS:@(self.videoActive)},@{EVENT_DEVICE:self.mic, EVENT_DEVICE_STATUS:@(self.audioActive)}]];
|
||||
|
||||
//add device
|
||||
event[EVENT_DEVICE] = self.camera;
|
||||
|
||||
//set device status
|
||||
event[EVENT_DEVICE_STATUS] = [NSNumber numberWithInt:self.videoActive];
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"got video change notification; is running? %x", self.videoActive]);
|
||||
|
||||
//alloc XPC connection
|
||||
xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.objective-see.OverSightXPC"];
|
||||
|
||||
//set remote object interface
|
||||
xpcConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(XPCProtocol)];
|
||||
|
||||
//resume
|
||||
[xpcConnection resume];
|
||||
|
||||
//init wait semaphore
|
||||
waitSema = dispatch_semaphore_create(0);
|
||||
|
||||
//tell XPC about video status
|
||||
// ->for example, when video is active, will stop baselining
|
||||
[[xpcConnection remoteObjectProxy] updateVideoStatus:self.videoActive reply:^{
|
||||
|
||||
//signal sema
|
||||
dispatch_semaphore_signal(waitSema);
|
||||
|
||||
}];
|
||||
|
||||
//wait until XPC is done
|
||||
// ->XPC reply block will signal semaphore
|
||||
dispatch_semaphore_wait(waitSema, DISPATCH_TIME_FOREVER);
|
||||
|
||||
//if video just started
|
||||
// ->ask for video procs from XPC
|
||||
if(YES == self.videoActive)
|
||||
{
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"querying XPC to get video process(s)");
|
||||
|
||||
//set allowed classes
|
||||
[xpcConnection.remoteObjectInterface setClasses: [NSSet setWithObjects: [NSMutableArray class], [NSNumber class], nil]
|
||||
forSelector: @selector(getVideoProcs:) argumentIndex: 0 ofReply: YES];
|
||||
|
||||
//invoke XPC service
|
||||
[[xpcConnection remoteObjectProxy] getVideoProcs:^(NSMutableArray* videoProcesses)
|
||||
{
|
||||
//close connection
|
||||
[xpcConnection invalidate];
|
||||
|
||||
//nil out
|
||||
xpcConnection = nil;
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"video procs from XPC: %@", videoProcesses]);
|
||||
|
||||
//generate notification for each process
|
||||
for(NSNumber* processID in videoProcesses)
|
||||
{
|
||||
//set pid
|
||||
event[EVENT_PROCESS_ID] = processID;
|
||||
|
||||
//generate notification
|
||||
[self generateNotification:event];
|
||||
}
|
||||
|
||||
//signal sema
|
||||
dispatch_semaphore_signal(waitSema);
|
||||
|
||||
}];
|
||||
|
||||
//wait until XPC is done
|
||||
// ->XPC reply block will signal semaphore
|
||||
dispatch_semaphore_wait(waitSema, DISPATCH_TIME_FOREVER);
|
||||
}
|
||||
|
||||
//video deactivated
|
||||
// ->close XPC connection and alert user
|
||||
else
|
||||
{
|
||||
//close connection
|
||||
[xpcConnection invalidate];
|
||||
|
||||
//nil out
|
||||
xpcConnection = nil;
|
||||
|
||||
//generate notification
|
||||
[self generateNotification:event];
|
||||
}
|
||||
|
||||
//poll for new video procs
|
||||
// ->this thread will exit itself as its checks the 'videoActive' iVar
|
||||
if(YES == self.videoActive)
|
||||
{
|
||||
//start monitor thread if needed
|
||||
if(YES != videoMonitorThread.isExecuting)
|
||||
{
|
||||
//alloc
|
||||
videoMonitorThread = [[NSThread alloc] initWithTarget:self selector:@selector(monitor4Procs) object:nil];
|
||||
|
||||
//start
|
||||
[self.videoMonitorThread start];
|
||||
}
|
||||
}
|
||||
|
||||
}//sync
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//register for video notifcations
|
||||
// ->block will invoke method on event
|
||||
-(BOOL)watchVideo:(CMIOObjectID)deviceID
|
||||
{
|
||||
//ret var
|
||||
BOOL bRegistered = NO;
|
||||
|
||||
//status var
|
||||
OSStatus status = -1;
|
||||
|
||||
//property struct
|
||||
CMIOObjectPropertyAddress propertyStruct = {0};
|
||||
|
||||
//init property struct's selector
|
||||
propertyStruct.mSelector = kAudioDevicePropertyDeviceIsRunningSomewhere;
|
||||
|
||||
//init property struct's scope
|
||||
propertyStruct.mScope = kAudioObjectPropertyScopeGlobal;
|
||||
|
||||
//init property struct's element
|
||||
propertyStruct.mElement = kAudioObjectPropertyElementMaster;
|
||||
|
||||
//block
|
||||
// ->invoked when video changes & just calls helper function
|
||||
CMIOObjectPropertyListenerBlock listenerBlock = ^(UInt32 inNumberAddresses, const CMIOObjectPropertyAddress addresses[])
|
||||
{
|
||||
//invoke helper function
|
||||
[self handleVideoNotification:deviceID addresses:addresses];
|
||||
|
||||
};
|
||||
|
||||
//register (add) property block listener
|
||||
status = CMIOObjectAddPropertyListenerBlock(deviceID, &propertyStruct, dispatch_get_main_queue(), listenerBlock);
|
||||
if(noErr != status)
|
||||
{
|
||||
//err msg
|
||||
//TODO: add
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//happy
|
||||
bRegistered = YES;
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return bRegistered;
|
||||
}
|
||||
|
||||
//determine if audio is active
|
||||
// ->sets 'audioActive' iVar
|
||||
-(void)setAudioDevStatus:(AudioObjectID)deviceID
|
||||
{
|
||||
//status var
|
||||
OSStatus status = -1;
|
||||
|
||||
//running flag
|
||||
UInt32 isRunning = -1;
|
||||
|
||||
//size of query flag
|
||||
UInt32 propertySize = 0;
|
||||
|
||||
//init size
|
||||
propertySize = sizeof(isRunning);
|
||||
|
||||
//query to get 'kAudioDevicePropertyDeviceIsRunningSomewhere' status
|
||||
status = AudioDeviceGetProperty(deviceID, 0, false, kAudioDevicePropertyDeviceIsRunningSomewhere, &propertySize, &isRunning);
|
||||
if(noErr != status)
|
||||
{
|
||||
//err msg
|
||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"getting status of audio device failed with %d", status]);
|
||||
|
||||
//set error
|
||||
isRunning = -1;
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//set iVar
|
||||
self.audioActive = isRunning;
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//helper function
|
||||
// ->determines if audio went active/inactive then invokes notification generator method
|
||||
-(void)handleAudioNotification:(AudioObjectID)deviceID
|
||||
{
|
||||
//event dictionary
|
||||
NSMutableDictionary* event = nil;
|
||||
|
||||
//init dictionary
|
||||
event = [NSMutableDictionary dictionary];
|
||||
|
||||
//sync
|
||||
@synchronized (self)
|
||||
{
|
||||
|
||||
//set status
|
||||
[self setAudioDevStatus:deviceID];
|
||||
|
||||
//send msg to status menu
|
||||
// ->update menu to show (all) devices & their status
|
||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]).statusBarMenuController updateStatusItemMenu:@[@{EVENT_DEVICE:self.mic, EVENT_DEVICE_STATUS:@(self.audioActive)},@{EVENT_DEVICE:self.camera, EVENT_DEVICE_STATUS:@(self.videoActive)}]];
|
||||
|
||||
//add device
|
||||
event[EVENT_DEVICE] = self.mic;
|
||||
|
||||
//set device status
|
||||
event[EVENT_DEVICE_STATUS] = [NSNumber numberWithInt:self.audioActive];
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"got audio change notification; is running? %x", self.audioActive]);
|
||||
|
||||
//generate notification
|
||||
[self generateNotification:event];
|
||||
|
||||
}
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//register for audio notifcations
|
||||
// ->block will invoke method on event
|
||||
-(BOOL)watchAudio:(AudioObjectID)deviceID
|
||||
{
|
||||
//ret var
|
||||
BOOL bRegistered = NO;
|
||||
|
||||
//property struct
|
||||
AudioObjectPropertyAddress propertyStruct = {0};
|
||||
|
||||
//init property struct's selector
|
||||
propertyStruct.mSelector = kAudioDevicePropertyDeviceIsRunningSomewhere;
|
||||
|
||||
//init property struct's scope
|
||||
propertyStruct.mScope = kAudioObjectPropertyScopeGlobal;
|
||||
|
||||
//init property struct's element
|
||||
propertyStruct.mElement = kAudioObjectPropertyElementMaster;
|
||||
|
||||
//block
|
||||
// ->invoked when audio changes & just calls helper function
|
||||
AudioObjectPropertyListenerBlock listenerBlock = ^(UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses)
|
||||
{
|
||||
[self handleAudioNotification:deviceID];
|
||||
};
|
||||
|
||||
|
||||
OSStatus ret = AudioObjectAddPropertyListenerBlock(deviceID, &propertyStruct, dispatch_get_main_queue(), listenerBlock);
|
||||
if (ret)
|
||||
{
|
||||
abort(); // FIXME
|
||||
}
|
||||
|
||||
|
||||
//happy
|
||||
bRegistered = YES;
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return bRegistered;
|
||||
|
||||
}
|
||||
|
||||
//build and display notification
|
||||
-(void)generateNotification:(NSDictionary*)event
|
||||
{
|
||||
//notification
|
||||
NSUserNotification* notification = nil;
|
||||
|
||||
//title
|
||||
NSMutableString* title = nil;
|
||||
|
||||
//details
|
||||
NSMutableString* details = nil;
|
||||
|
||||
//process name
|
||||
NSString* processName = nil;
|
||||
|
||||
//alloc notificaiton
|
||||
notification = [[NSUserNotification alloc] init];
|
||||
|
||||
//alloc title
|
||||
title = [NSMutableString string];
|
||||
|
||||
//alloc details
|
||||
details = [NSMutableString string];
|
||||
|
||||
//set title
|
||||
// ->audio device
|
||||
if(YES == [event[EVENT_DEVICE] isKindOfClass:NSClassFromString(@"AVCaptureHALDevice")])
|
||||
{
|
||||
//add
|
||||
[title appendString:@"Audio Device"];
|
||||
}
|
||||
//add source
|
||||
// ->video device
|
||||
else
|
||||
{
|
||||
//add
|
||||
[title appendString:@"Video Device"];
|
||||
}
|
||||
|
||||
//add action
|
||||
// ->device went inactive
|
||||
if(YES == [DEVICE_INACTIVE isEqual:event[EVENT_DEVICE_STATUS]])
|
||||
{
|
||||
//add
|
||||
[title appendString:@" became inactive"];
|
||||
}
|
||||
//add action
|
||||
// ->device went active
|
||||
else
|
||||
{
|
||||
//add
|
||||
[title appendString:@" became active"];
|
||||
}
|
||||
|
||||
//customize buttons
|
||||
// ->for mic or inactive events, just say 'ok'
|
||||
if( (YES == [event[EVENT_DEVICE] isKindOfClass:NSClassFromString(@"AVCaptureHALDevice")]) ||
|
||||
(YES == [DEVICE_INACTIVE isEqual:event[EVENT_DEVICE_STATUS]]) )
|
||||
{
|
||||
//set other button title
|
||||
notification.otherButtonTitle = @"ok";
|
||||
|
||||
//remove action button
|
||||
notification.hasActionButton = NO;
|
||||
}
|
||||
|
||||
//customize buttons
|
||||
// ->for activatated video; allow/block
|
||||
else
|
||||
{
|
||||
//set other button title
|
||||
notification.otherButtonTitle = @"allow";
|
||||
|
||||
//set action title
|
||||
notification.actionButtonTitle = @"block";
|
||||
|
||||
//get process name
|
||||
// TODO: see 'determineName' in BB (to get name from bundle, etc)
|
||||
processName = [getProcessPath([event[EVENT_PROCESS_ID] intValue]) lastPathComponent];
|
||||
|
||||
//set pid in user info
|
||||
// ->allows code to try kill proc (later) if user clicks 'block'
|
||||
notification.userInfo = @{EVENT_PROCESS_ID:event[EVENT_PROCESS_ID]};
|
||||
|
||||
//set details
|
||||
// ->name of process using it / icon too?
|
||||
[notification setInformativeText:[NSString stringWithFormat:@"%@ (%@)", processName, event[EVENT_PROCESS_ID]]];
|
||||
|
||||
}
|
||||
|
||||
//icon issues
|
||||
//http://stackoverflow.com/questions/11856766/osx-notification-center-icon
|
||||
|
||||
//contentImage for process icon?
|
||||
|
||||
//custom icon?
|
||||
//http://stackoverflow.com/questions/24923979/nsusernotification-customisable-app-icon
|
||||
|
||||
//icon set automatically?
|
||||
//[notification set]
|
||||
|
||||
//set title
|
||||
[notification setTitle:title];
|
||||
|
||||
//set subtitle
|
||||
[notification setSubtitle:((AVCaptureDevice*)event[EVENT_DEVICE]).localizedName];
|
||||
|
||||
//set details
|
||||
// ->name of process using it / icon too?
|
||||
//[notification setInformativeText:@"some process (1337)"];
|
||||
|
||||
//set notification
|
||||
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];
|
||||
|
||||
//deliver notification
|
||||
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//always present notifications
|
||||
-(BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
//automatically invoked when user interacts w/ the notification popup
|
||||
// ->only action we care about, is killing the process if they click 'block'
|
||||
-(void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
|
||||
{
|
||||
//xpc connection
|
||||
__block NSXPCConnection* xpcConnection = nil;
|
||||
|
||||
//process id
|
||||
NSNumber* processID = nil;
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"use responded to notification: %@", notification]);
|
||||
|
||||
//for video
|
||||
// ->kill process if user clicked 'block'
|
||||
if( (YES == [notification.actionButtonTitle isEqualToString:@"block"]) &&
|
||||
(notification.activationType == NSUserNotificationActivationTypeActionButtonClicked))
|
||||
{
|
||||
//extract process id
|
||||
processID = notification.userInfo[EVENT_PROCESS_ID];
|
||||
if(nil == processID)
|
||||
{
|
||||
//err msg
|
||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to extract process id from notification, %@", notification.userInfo]);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//alloc XPC connection
|
||||
xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.objective-see.OverSightXPC"];
|
||||
|
||||
//set remote object interface
|
||||
xpcConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(XPCProtocol)];
|
||||
|
||||
//resume
|
||||
[xpcConnection resume];
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"invoking XPC method to kill: %@", processID]);
|
||||
|
||||
//invoke XPC method 'killProcess' to terminate
|
||||
[[xpcConnection remoteObjectProxy] killProcess:processID reply:^(BOOL wasKilled)
|
||||
{
|
||||
//check for err
|
||||
if(YES != wasKilled)
|
||||
{
|
||||
//err msg
|
||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to kill/block: %@", processID]);
|
||||
|
||||
}
|
||||
|
||||
//close connection
|
||||
[xpcConnection invalidate];
|
||||
|
||||
//nil out
|
||||
xpcConnection = nil;
|
||||
}];
|
||||
|
||||
}//user clicked 'block'
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//monitor for new procs (video only at the moment)
|
||||
// ->runs until video is no longer in use (set elsewhere)
|
||||
-(void)monitor4Procs
|
||||
{
|
||||
//xpc connection
|
||||
NSXPCConnection* xpcConnection = nil;
|
||||
|
||||
//wait semaphore
|
||||
dispatch_semaphore_t waitSema = nil;
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"video is active, so polling for new procs");
|
||||
|
||||
//alloc XPC connection
|
||||
xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.objective-see.OverSightXPC"];
|
||||
|
||||
//set remote object interface
|
||||
xpcConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(XPCProtocol)];
|
||||
|
||||
//set classes
|
||||
// ->arrays/numbers ok to vend
|
||||
[xpcConnection.remoteObjectInterface setClasses: [NSSet setWithObjects: [NSMutableArray class], [NSNumber class], nil]
|
||||
forSelector: @selector(getVideoProcs:) argumentIndex: 0 ofReply: YES];
|
||||
//resume
|
||||
[xpcConnection resume];
|
||||
|
||||
//poll while video is active
|
||||
while(YES == self.videoActive)
|
||||
{
|
||||
//init wait semaphore
|
||||
waitSema = dispatch_semaphore_create(0);
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"asking XPC for (new) video procs");
|
||||
|
||||
//invoke XPC service to get (new) video procs
|
||||
// ->will generate user notifications for any new processes
|
||||
[[xpcConnection remoteObjectProxy] getVideoProcs:^(NSMutableArray* videoProcesses)
|
||||
{
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"new video procs: %@", videoProcesses]);
|
||||
|
||||
//generate a notification for each process
|
||||
// ->double check video is still active though...
|
||||
for(NSNumber* processID in videoProcesses)
|
||||
{
|
||||
//check video
|
||||
if(YES != self.videoActive)
|
||||
{
|
||||
//exit loop
|
||||
break;
|
||||
}
|
||||
|
||||
//generate notification
|
||||
[self generateNotification:@{EVENT_DEVICE:self.camera, EVENT_DEVICE_STATUS:DEVICE_ACTIVE, EVENT_PROCESS_ID:processID}];
|
||||
}
|
||||
|
||||
//signal sema
|
||||
dispatch_semaphore_signal(waitSema);
|
||||
|
||||
}];
|
||||
|
||||
//wait until XPC is done
|
||||
// ->XPC reply block will signal semaphore
|
||||
dispatch_semaphore_wait(waitSema, DISPATCH_TIME_FOREVER);
|
||||
|
||||
//nap
|
||||
[NSThread sleepForTimeInterval:5.0f];
|
||||
|
||||
}//run until video (camera) is off
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
//close connection
|
||||
[xpcConnection invalidate];
|
||||
|
||||
//nil out
|
||||
xpcConnection = nil;
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"exiting monitor thread");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// AppDelegate.h
|
||||
// Test Application Helper
|
||||
//
|
||||
// Created by Patrick Wardle on 9/10/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "AVMonitor.h"
|
||||
#import "EventMonitor.h"
|
||||
#import "StatusBarMenu.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||
|
||||
/* PROPERTIES */
|
||||
|
||||
//status bar menu
|
||||
@property(nonatomic, retain)StatusBarMenu* statusBarMenuController;
|
||||
|
||||
//(camera event) monitor class
|
||||
@property(nonatomic, retain)EventMonitor* monitor;
|
||||
|
||||
@property(nonatomic, retain)AVMonitor* avMonitor;
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
//
|
||||
// AppDelegate.m
|
||||
// Test Application Helper
|
||||
//
|
||||
// Created by Patrick Wardle on 9/10/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import "Logging.h"
|
||||
#import "AppDelegate.h"
|
||||
|
||||
|
||||
@interface AppDelegate ()
|
||||
|
||||
@property (weak) IBOutlet NSWindow *window;
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
|
||||
@synthesize monitor;
|
||||
@synthesize avMonitor;
|
||||
@synthesize statusBarMenuController;
|
||||
|
||||
|
||||
//app's main interface
|
||||
// ->load status bar and kick off monitor
|
||||
-(void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
||||
{
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"starting login item");
|
||||
|
||||
//init/load status bar
|
||||
[self loadStatusBar];
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"initialized/loaded status bar (icon/menu)");
|
||||
|
||||
//create/init av event monitor
|
||||
avMonitor = [[AVMonitor alloc] init];
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"alloc/init'd AV monitor");
|
||||
|
||||
//start monitoring
|
||||
// ->sets up audio/video callbacks
|
||||
[avMonitor monitor];
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"AV monitor off and running");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//initialize status menu bar
|
||||
-(void)loadStatusBar
|
||||
{
|
||||
//alloc/load nib
|
||||
statusBarMenuController = [[StatusBarMenu alloc] init];
|
||||
|
||||
//init menu
|
||||
[self.statusBarMenuController setupStatusItem];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,666 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6245" systemVersion="13F34" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6245"/>
|
||||
</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"/>
|
||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
|
||||
<items>
|
||||
<menuItem title="Test Application Helper" id="1Xt-HY-uBw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Test Application Helper" systemMenu="apple" id="uQy-DD-JDr">
|
||||
<items>
|
||||
<menuItem title="About Test Application Helper" 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 Test Application Helper" 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 Test Application Helper" 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="Test Application Helper Help" keyEquivalent="?" id="FKE-Sm-Kum">
|
||||
<connections>
|
||||
<action selector="showHelp:" target="-1" id="y7X-2Q-9no"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</objects>
|
||||
</document>
|
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// ProcessMonitor.h
|
||||
// BlockBlock
|
||||
//
|
||||
// Created by Patrick Wardle on 10/19/14.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
//#import "OrderedDictionary.h"
|
||||
|
||||
/*
|
||||
//custom struct
|
||||
// format of data that's broadcast from kext
|
||||
struct processStartEvent
|
||||
{
|
||||
//process pid
|
||||
// ->id's all chunks
|
||||
pid_t pid;
|
||||
|
||||
//process uid
|
||||
uid_t uid;
|
||||
|
||||
//process ppid
|
||||
pid_t ppid;
|
||||
|
||||
//process path
|
||||
char path[0];
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@interface EventMonitor : NSObject
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* PROPERTIES */
|
||||
|
||||
//process list
|
||||
//@property(nonatomic, retain)OrderedDictionary* processList;
|
||||
|
||||
//dictionary of partial events
|
||||
//@property(nonatomic, retain)NSMutableDictionary* partialProcessEvents;
|
||||
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//kicks off thread to monitor
|
||||
-(BOOL)monitor;
|
||||
|
||||
//thread function
|
||||
// ->recv() process creation notification events from kext
|
||||
-(void)recvProcNotifications;
|
||||
|
||||
@end
|
|
@ -0,0 +1,351 @@
|
|||
//
|
||||
// ProcessMonitor.m
|
||||
// BlockBlock
|
||||
//
|
||||
// Created by Patrick Wardle on 10/19/14.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Consts.h"
|
||||
#import "Logging.h"
|
||||
//#import "Process.h"
|
||||
#import "Utilities.h"
|
||||
#import "EventMonitor.h"
|
||||
//#import "OrderedDictionary.h"
|
||||
|
||||
#import <stdio.h>
|
||||
#import <stdlib.h>
|
||||
#import <arpa/inet.h>
|
||||
#import <sys/ioctl.h>
|
||||
#import <sys/socket.h>
|
||||
#import <sys/kern_event.h>
|
||||
|
||||
//TODO: move into shared file
|
||||
//vendor id string
|
||||
#define OBJECTIVE_SEE_VENDOR "com.objectiveSee"
|
||||
|
||||
//process camera event
|
||||
#define PROCESS_CAMERA_EVENT 0x1
|
||||
|
||||
|
||||
@implementation EventMonitor
|
||||
|
||||
//@synthesize processList;
|
||||
//@synthesize partialProcessEvents;
|
||||
|
||||
//init
|
||||
-(id)init
|
||||
{
|
||||
//init super
|
||||
self = [super init];
|
||||
if(nil != self)
|
||||
{
|
||||
//init process list
|
||||
//processList = [[OrderedDictionary alloc] init];
|
||||
|
||||
//init partial process event dictionary
|
||||
//partialProcessEvents = [NSMutableDictionary dictionary];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
//kick off threads to monitor
|
||||
// ->dtrace/audit pipe/app callback
|
||||
-(BOOL)monitor
|
||||
{
|
||||
//return var
|
||||
BOOL bRet = NO;
|
||||
|
||||
//start thread to get process creation notifications from kext
|
||||
[NSThread detachNewThreadSelector:@selector(recvProcNotifications) toTarget:self withObject:nil];
|
||||
|
||||
//no errors
|
||||
bRet = YES;
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
//thread function
|
||||
// ->recv() process creation notification events
|
||||
-(void)recvProcNotifications
|
||||
{
|
||||
//status var
|
||||
int status = -1;
|
||||
|
||||
//system socket
|
||||
int systemSocket = -1;
|
||||
|
||||
//struct for vendor code
|
||||
// ->set via call to ioctl/SIOCGKEVVENDOR
|
||||
struct kev_vendor_code vendorCode = {0};
|
||||
|
||||
//struct for kernel request
|
||||
// ->set filtering options
|
||||
struct kev_request kevRequest = {0};
|
||||
|
||||
//struct for broadcast data from the kext
|
||||
struct kern_event_msg *kernEventMsg = {0};
|
||||
|
||||
//message from kext
|
||||
// ->size is cumulation of header, pid
|
||||
char kextMsg[KEV_MSG_HEADER_SIZE + sizeof(pid_t)] = {0};
|
||||
|
||||
//bytes received from system socket
|
||||
ssize_t bytesReceived = -1;
|
||||
|
||||
//process path
|
||||
// ->could be partial...
|
||||
char path[MAXPATHLEN+1] = {0};
|
||||
|
||||
//length of path bytes
|
||||
// ->might not be NULL terminated, so have to calc manually
|
||||
int pathLength = 0;
|
||||
|
||||
//cumulative path
|
||||
// ->when path is long & thus chunked
|
||||
NSMutableString* cumulativePath = nil;
|
||||
|
||||
//custom struct
|
||||
// ->process data from kext
|
||||
//struct processStartEvent* procStartEvent = NULL;
|
||||
|
||||
//pid of process that triggered alert
|
||||
pid_t triggerProcess = -1;
|
||||
|
||||
//process info
|
||||
//NSMutableDictionary* procInfo = nil;
|
||||
|
||||
//process object
|
||||
//Process* processObj = nil;
|
||||
|
||||
//create system socket
|
||||
systemSocket = socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT);
|
||||
if(-1 == systemSocket)
|
||||
{
|
||||
//set status var
|
||||
status = errno;
|
||||
|
||||
//err msg
|
||||
//logMsg(LOG_ERR, [NSString stringWithFormat:@"socket() failed with %d", status]);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//set vendor name string
|
||||
strncpy(vendorCode.vendor_string, OBJECTIVE_SEE_VENDOR, KEV_VENDOR_CODE_MAX_STR_LEN);
|
||||
|
||||
//get vendor name -> vendor code mapping
|
||||
status = ioctl(systemSocket, SIOCGKEVVENDOR, &vendorCode);
|
||||
if(0 != status)
|
||||
{
|
||||
//err msg
|
||||
//logMsg(LOG_ERR, [NSString stringWithFormat:@"ioctl(...,SIOCGKEVVENDOR,...) failed with %d", status]);
|
||||
|
||||
//goto bail;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//init filtering options
|
||||
// ->only interested in objective-see's events
|
||||
kevRequest.vendor_code = vendorCode.vendor_code;
|
||||
|
||||
//...any class
|
||||
kevRequest.kev_class = KEV_ANY_CLASS;
|
||||
|
||||
//...any subclass
|
||||
kevRequest.kev_subclass = KEV_ANY_SUBCLASS;
|
||||
|
||||
//tell kernel what we want to filter on
|
||||
status = ioctl(systemSocket, SIOCSKEVFILT, &kevRequest);
|
||||
if(0 != status)
|
||||
{
|
||||
//err msg
|
||||
//logMsg(LOG_ERR, [NSString stringWithFormat:@"ioctl(...,SIOCSKEVFILT,...) failed with %d", status]);
|
||||
|
||||
//goto bail;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//dbg msg
|
||||
//logMsg(LOG_DEBUG, @"created system socket & set options, now entering recv() loop");
|
||||
|
||||
//foreverz
|
||||
// ->listen/parse process creation events from kext
|
||||
while(YES)
|
||||
{
|
||||
//ask the kext for process began events
|
||||
// ->will block until event is ready
|
||||
bytesReceived = recv(systemSocket, kextMsg, sizeof(kextMsg), 0);
|
||||
|
||||
//type cast
|
||||
// ->to access kev_event_msg header
|
||||
kernEventMsg = (struct kern_event_msg*)kextMsg;
|
||||
|
||||
//sanity check
|
||||
// ->make sure data recv'd looks ok, sizewise
|
||||
if( (bytesReceived < KEV_MSG_HEADER_SIZE) ||
|
||||
(bytesReceived != kernEventMsg->total_size))
|
||||
{
|
||||
//dbg msg
|
||||
//logMsg(LOG_DEBUG, [NSString stringWithFormat:@"recv count: %d, wanted: %d", (int)bytesReceived, kernEventMsg->total_size]);
|
||||
|
||||
//ignore
|
||||
continue;
|
||||
}
|
||||
|
||||
//only care about 'process began' events
|
||||
if(PROCESS_CAMERA_EVENT != kernEventMsg->event_code)
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//dbg msg
|
||||
//logMsg(LOG_DEBUG, [NSString stringWithFormat:@"got msg from kernel, size: %d", kernEventMsg->total_size]);
|
||||
|
||||
//zero out process path
|
||||
bzero(path, sizeof(path));
|
||||
|
||||
//typecast custom data
|
||||
// ->begins right after header
|
||||
//procStartEvent = (struct processStartEvent*)&kernEventMsg->event_data[0];
|
||||
|
||||
//dbg msg(s)
|
||||
//logMsg(LOG_DEBUG, [NSString stringWithFormat:@" path (in this chunk): %s \n", procStartEvent->path]);
|
||||
//logMsg(LOG_DEBUG, [NSString stringWithFormat:@" pid: %d ppid: %d uid: %d\n\n", procStartEvent->pid, procStartEvent->ppid, procStartEvent->uid]);
|
||||
|
||||
//init proc info dictionary
|
||||
//procInfo = [NSMutableDictionary dictionary];
|
||||
|
||||
triggerProcess = (pid_t)kernEventMsg->event_data[0];
|
||||
|
||||
NSLog(@"proc %d triggered alert", triggerProcess);
|
||||
|
||||
/*
|
||||
//save pid
|
||||
procInfo[@"pid"] = [NSNumber numberWithInt:procStartEvent->pid];
|
||||
|
||||
//save uid
|
||||
procInfo[@"uid"] = [NSNumber numberWithInt:procStartEvent->uid];
|
||||
|
||||
//save ppid
|
||||
procInfo[@"ppid"] = [NSNumber numberWithInt:procStartEvent->ppid];
|
||||
|
||||
//calc number of bytes in path
|
||||
// ->might not be NULL terminated, so have to do it manually
|
||||
pathLength = kernEventMsg->total_size - KEV_MSG_HEADER_SIZE - sizeof(pid_t) - sizeof(uid_t) - sizeof(pid_t);
|
||||
|
||||
//sanity check
|
||||
// ->should never happen...
|
||||
if(pathLength > MAXPATHLEN)
|
||||
{
|
||||
//ignore
|
||||
continue;
|
||||
}
|
||||
|
||||
//copy path into buffer
|
||||
memcpy(path, (const char*)procStartEvent->path, pathLength);
|
||||
|
||||
//NULL terminate it
|
||||
path[pathLength] = 0x0;
|
||||
|
||||
//final chunk will end in NULL
|
||||
if(0x0 == *(((char*)kernEventMsg->event_data) + kernEventMsg->total_size-KEV_MSG_HEADER_SIZE-1))
|
||||
{
|
||||
//check if there are path components
|
||||
// ->pid is key into partial process list
|
||||
cumulativePath = self.partialProcessEvents[procInfo[@"pid"]];
|
||||
|
||||
//finalize path
|
||||
// ->append this last path component chunk
|
||||
if(nil != cumulativePath)
|
||||
{
|
||||
//append
|
||||
[cumulativePath appendString:[NSString stringWithUTF8String:path]];
|
||||
|
||||
//set final path
|
||||
procInfo[@"path"] = cumulativePath;
|
||||
|
||||
//remove entry from partial list
|
||||
[self.partialProcessEvents removeObjectForKey:procInfo[@"pid"]];
|
||||
}
|
||||
//path wasn't chunked
|
||||
// ->can just use path as is
|
||||
else
|
||||
{
|
||||
//set final path
|
||||
procInfo[@"path"] = [NSString stringWithUTF8String:path];
|
||||
}
|
||||
|
||||
//dbg msg
|
||||
//logMsg(LOG_DEBUG, [NSString stringWithFormat:@"new process: %@", procInfo[@"path"]]);
|
||||
|
||||
//now, create process object
|
||||
processObj = [[Process alloc] initWithPid:procStartEvent->pid infoDictionary:procInfo];
|
||||
|
||||
//sync process list
|
||||
// ->then insert it into list
|
||||
@synchronized(self.processList)
|
||||
{
|
||||
//trim list if needed
|
||||
if(self.processList.count >= PROCESS_LIST_MAX_SIZE)
|
||||
{
|
||||
//toss first (oldest) item
|
||||
[self.processList removeObjectForKey:[self.processList keyAtIndex:0]];
|
||||
}
|
||||
|
||||
//insert process at end
|
||||
[self.processList addObject:processObj forKey:procInfo[@"pid"] atStart:NO];
|
||||
|
||||
}//sync
|
||||
|
||||
}//final chunk
|
||||
|
||||
//non-final chunk
|
||||
// ->insert it, or append to partial process list
|
||||
else
|
||||
{
|
||||
//try grab existing (partial) path
|
||||
cumulativePath = self.partialProcessEvents[procInfo[@"pid"]];
|
||||
|
||||
//check if there are path components already...
|
||||
// ->i.e. this is just another chunk, so append
|
||||
if(nil != cumulativePath)
|
||||
{
|
||||
//append
|
||||
[cumulativePath appendString:[NSString stringWithUTF8String:path]];
|
||||
}
|
||||
//new process
|
||||
// ->insert into partial process list
|
||||
else
|
||||
{
|
||||
//insert
|
||||
self.partialProcessEvents[procInfo[@"pid"]] = [NSMutableString stringWithUTF8String:path];
|
||||
}
|
||||
|
||||
}//non-final chunk
|
||||
|
||||
*/
|
||||
|
||||
}//while(YES)
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
//close socket
|
||||
if(-1 != systemSocket)
|
||||
{
|
||||
//close
|
||||
close(systemSocket);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,68 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "16x16",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_16x16.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "16x16",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_16x16@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "32x32",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_32x32.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "32x32",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_32x32@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "128x128",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_128x128.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "128x128",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_128x128@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "256x256",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_256x256.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "256x256",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_256x256@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "512x512",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_512x512.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "512x512",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_512x512@2x.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 158 KiB |
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 27 KiB |
|
@ -0,0 +1,38 @@
|
|||
<?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></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.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.0</string>
|
||||
<key>LSBackgroundOnly</key>
|
||||
<true/>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright (c) 2016 Objective-See. All rights reserved.</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<key>NSUserNotificationAlertStyle</key>
|
||||
<string>alert</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"filename" : "statusIcon.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"filename" : "statusIcon@2x.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// StatusBarMenu.h
|
||||
// OverSight
|
||||
//
|
||||
// Created by Patrick Wardle on 1/4/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface StatusBarMenu : NSObject
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//status item
|
||||
@property (nonatomic, strong, readwrite) NSStatusItem *statusItem;
|
||||
|
||||
//popover
|
||||
@property (retain, nonatomic)NSPopover *popover;
|
||||
|
||||
//enabled flag
|
||||
@property BOOL isEnabled;
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//setup status item
|
||||
// ->init button, show popover, etc
|
||||
-(void)setupStatusItem;
|
||||
|
||||
//create/update status item menu
|
||||
-(void)updateStatusItemMenu:(NSArray*)devices;
|
||||
|
||||
//init a menu item
|
||||
-(NSMenuItem*)initializeMenuItem:(NSString*)title action:(SEL)action;
|
||||
|
||||
//menu handler for 'enable'/'disable'
|
||||
// ->toggle blockblock & update menu
|
||||
//-(void)toggle:(id)sender;
|
||||
|
||||
//menu handler for 'uninstall'
|
||||
// ->kick off uninstall
|
||||
//-(void)uninstall:(id)sender;
|
||||
|
||||
//menu handler for 'perferences'
|
||||
// ->show preferences window
|
||||
-(void)preferences:(id)sender;
|
||||
|
||||
@end
|
|
@ -0,0 +1,295 @@
|
|||
//
|
||||
// StatusBarMenu.m
|
||||
// OverSight
|
||||
//
|
||||
// Created by Patrick Wardle on 1/4/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import "Logging.h"
|
||||
#import "AppDelegate.h"
|
||||
#import "StatusBarMenu.h"
|
||||
|
||||
#import <CoreMediaIO/CMIOHardware.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
|
||||
@implementation StatusBarMenu
|
||||
|
||||
@synthesize isEnabled;
|
||||
|
||||
//init method
|
||||
// ->set some intial flags, etc
|
||||
-(id)init
|
||||
{
|
||||
//load from nib
|
||||
self = [super init];
|
||||
if(self != nil)
|
||||
{
|
||||
//set flag
|
||||
self.isEnabled = YES;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
//setup status item
|
||||
// ->init button, show popover, etc
|
||||
-(void)setupStatusItem
|
||||
{
|
||||
//status bar image
|
||||
NSImage *image = nil;
|
||||
|
||||
//init status item
|
||||
self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
|
||||
|
||||
//init image
|
||||
image = [NSImage imageNamed:@"statusIcon"];
|
||||
|
||||
//tell OS to handle image
|
||||
// ->dark mode, etc
|
||||
[image setTemplate:YES];
|
||||
|
||||
//set image
|
||||
self.statusItem.image = image;
|
||||
|
||||
//init menu
|
||||
// ->enumerator will re-invoke with devices and their status
|
||||
[self updateStatusItemMenu:nil];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//create/update status item menu
|
||||
-(void)updateStatusItemMenu:(NSArray*)devices
|
||||
{
|
||||
//menu
|
||||
NSMenu* menu = nil;
|
||||
|
||||
//array of active devices
|
||||
NSMutableArray* activeDevices = nil;
|
||||
|
||||
//array of inactive devices
|
||||
NSMutableArray* inactiveDevices = nil;
|
||||
|
||||
//string for device name/emoji
|
||||
NSMutableString* deviceDetails = nil;
|
||||
|
||||
//alloc/init window
|
||||
menu = [[NSMenu alloc] init];
|
||||
|
||||
//alloc array for active devices
|
||||
activeDevices = [NSMutableArray array];
|
||||
|
||||
//alloc array for inactive devices
|
||||
inactiveDevices = [NSMutableArray array];
|
||||
|
||||
//add status msg
|
||||
[menu addItemWithTitle:@"OVERSIGHT: monitoring 🎤 + 📸" action:NULL keyEquivalent:@""];
|
||||
|
||||
//add top separator
|
||||
[menu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
//iterate over all devices
|
||||
// ->classify each, and built details string for menu
|
||||
for(NSDictionary* device in devices)
|
||||
{
|
||||
//init string for name/etc
|
||||
deviceDetails = [NSMutableString string];
|
||||
|
||||
//add device emoji
|
||||
// ->audio device
|
||||
if(YES == [device[EVENT_DEVICE] isKindOfClass:NSClassFromString(@"AVCaptureHALDevice")])
|
||||
{
|
||||
//add
|
||||
[deviceDetails appendString:@" 🎤 "];
|
||||
}
|
||||
//add device emoji
|
||||
// ->video device
|
||||
else
|
||||
{
|
||||
//add
|
||||
[deviceDetails appendString:@" 📸 "];
|
||||
}
|
||||
|
||||
//add device name
|
||||
[deviceDetails appendString:((AVCaptureDevice*)device[EVENT_DEVICE]).localizedName];
|
||||
|
||||
//classify
|
||||
// ->active devices
|
||||
if(DEVICE_ACTIVE.intValue == [device[EVENT_DEVICE_STATUS] intValue])
|
||||
{
|
||||
//add
|
||||
[activeDevices addObject:deviceDetails];
|
||||
}
|
||||
//classify
|
||||
// ->inactive devices
|
||||
else
|
||||
{
|
||||
//add
|
||||
[inactiveDevices addObject:deviceDetails];
|
||||
}
|
||||
}
|
||||
|
||||
//add active devices to menu
|
||||
if(0 != activeDevices.count)
|
||||
{
|
||||
//add title
|
||||
[menu addItem:[self initializeMenuItem:@"Active Devices" action:NULL]];
|
||||
|
||||
//add each
|
||||
for(NSString* deviceDetails in activeDevices)
|
||||
{
|
||||
[menu addItem:[self initializeMenuItem:deviceDetails action:NULL]];
|
||||
}
|
||||
}
|
||||
//when no active devices
|
||||
// ->add title to reflect that fact
|
||||
else
|
||||
{
|
||||
//add
|
||||
[menu addItem:[self initializeMenuItem:@"No Active Devices" action:NULL]];
|
||||
}
|
||||
|
||||
//add item separator
|
||||
[menu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
//add inactive devices to menu
|
||||
if(0 != inactiveDevices.count)
|
||||
{
|
||||
//add title
|
||||
[menu addItem:[self initializeMenuItem:@"Inactive Devices" action:NULL]];
|
||||
|
||||
//add each
|
||||
for(NSString* deviceDetails in inactiveDevices)
|
||||
{
|
||||
[menu addItem:[self initializeMenuItem:deviceDetails action:NULL]];
|
||||
}
|
||||
}
|
||||
//when no inactive devices
|
||||
// ->add title to reflect that fact
|
||||
else
|
||||
{
|
||||
//add
|
||||
[menu addItem:[self initializeMenuItem:@"No Inactive Devices" action:NULL]];
|
||||
}
|
||||
|
||||
//add item separator
|
||||
[menu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
//create/add menu item
|
||||
// ->'preferences'
|
||||
[menu addItem:[self initializeMenuItem:@"Preferences" action:@selector(preferences:)]];
|
||||
|
||||
//add bottom separator
|
||||
[menu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
//create/add menu item
|
||||
// ->'about'
|
||||
[menu addItem:[self initializeMenuItem:@"Quit" action:@selector(quit:)]];
|
||||
|
||||
//tie menu to status item
|
||||
self.statusItem.menu = menu;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//init a menu item
|
||||
-(NSMenuItem*)initializeMenuItem:(NSString*)title action:(SEL)action
|
||||
{
|
||||
//menu item
|
||||
NSMenuItem* menuItem = nil;
|
||||
|
||||
//alloc menu item
|
||||
// ->toggle ('enable'/'disable')
|
||||
menuItem = [[NSMenuItem alloc] initWithTitle:title action:action keyEquivalent:@""];
|
||||
|
||||
//enabled
|
||||
menuItem.enabled = YES;
|
||||
|
||||
//self
|
||||
menuItem.target = self;
|
||||
|
||||
return menuItem;
|
||||
}
|
||||
|
||||
#pragma mark - Menu actions
|
||||
|
||||
//handler for 'quit'
|
||||
// ->just exit the application
|
||||
-(void)quit:(id)sender
|
||||
{
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"user clicked 'exit', so goodbye!");
|
||||
|
||||
//exit
|
||||
[[NSApplication sharedApplication] terminate:nil];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//handler for 'preferences' menu item
|
||||
// ->launch main application which will show prefs
|
||||
-(void)preferences:(id)sender
|
||||
{
|
||||
|
||||
//this works when packaged into Login Item into top-level app
|
||||
NSArray *pathComponents = [[[NSBundle mainBundle] bundlePath] pathComponents];
|
||||
pathComponents = [pathComponents subarrayWithRange:NSMakeRange(0, [pathComponents count] - 4)];
|
||||
NSString *path = [NSString pathWithComponents:pathComponents];
|
||||
[[NSWorkspace sharedWorkspace] launchApplication:path];
|
||||
|
||||
|
||||
|
||||
/*
|
||||
//controller for preferences window
|
||||
PrefsWindowController* prefsWindowController = nil;
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"displaying preferences window");
|
||||
|
||||
//grab controller
|
||||
prefsWindowController = ((AppDelegate*)[[NSApplication sharedApplication] delegate]).prefsWindowController;
|
||||
|
||||
//show pref window
|
||||
[prefsWindowController showWindow:sender];
|
||||
|
||||
//invoke function in background that will make window modal
|
||||
// ->waits until window is non-nil
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
|
||||
//make modal
|
||||
makeModal(prefsWindowController);
|
||||
|
||||
});
|
||||
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//menu handler that's automatically invoked when user clicks 'about'
|
||||
// ->load objective-see's documentation for BlockBlock
|
||||
-(void)about:(id)sender
|
||||
{
|
||||
/*
|
||||
|
||||
//alloc/init about window
|
||||
infoWindowController = [[InfoWindowController alloc] initWithWindowNibName:@"InfoWindow"];
|
||||
|
||||
//configure label and button
|
||||
[self.infoWindowController configure:[NSString stringWithFormat:@"version: %@", getAppVersion()] buttonTitle:@"more info"];
|
||||
|
||||
//center window
|
||||
[[self.infoWindowController window] center];
|
||||
|
||||
//show it
|
||||
[self.infoWindowController showWindow:self];
|
||||
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,13 @@
|
|||
//
|
||||
// main.m
|
||||
// Test Application Helper
|
||||
//
|
||||
// Created by Patrick Wardle on 9/10/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
return NSApplicationMain(argc, argv);
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
//
|
||||
// AppDelegate.h
|
||||
// Test Application
|
||||
//
|
||||
// Created by Patrick Wardle on 9/10/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||
|
||||
@property (weak) IBOutlet NSButton *loginButton;
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// AppDelegate.m
|
||||
// Test Application
|
||||
//
|
||||
// Created by Patrick Wardle on 9/10/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import <ServiceManagement/ServiceManagement.h>
|
||||
|
||||
@interface AppDelegate ()
|
||||
|
||||
@property (weak) IBOutlet NSWindow *window;
|
||||
@end
|
||||
|
||||
//TODO: add uninstall?
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
||||
{
|
||||
// Insert code here to initialize your application
|
||||
|
||||
self.loginButton.state = [[NSUserDefaults standardUserDefaults] boolForKey:@"LoginEnabled"];
|
||||
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(NSNotification *)aNotification
|
||||
{
|
||||
// Insert code here to tear down your application
|
||||
}
|
||||
|
||||
//automatically close when user closes window
|
||||
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (IBAction)loginButtonPressed:(NSButton *)sender
|
||||
{
|
||||
if (!SMLoginItemSetEnabled((__bridge CFStringRef)@"com.objective-see.OverSightHelper", [sender state])) {
|
||||
NSLog(@"Login Item Was Not Successful");
|
||||
}
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setBool:[sender state] forKey:@"LoginEnabled"];
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,714 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="15G1004" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
|
||||
</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="loginButton" destination="rVS-uv-DNf" id="uR0-zX-h7m"/>
|
||||
<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="OverSight" id="1Xt-HY-uBw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="OverSight" systemMenu="apple" id="uQy-DD-JDr">
|
||||
<items>
|
||||
<menuItem title="About OverSight" 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 OverSight" 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 OverSight" 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="OverSight 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="OverSight Preferences" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="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="1920" height="1057"/>
|
||||
<view key="contentView" id="EiT-Mj-1SZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="rVS-uv-DNf">
|
||||
<rect key="frame" x="307" y="61" width="119" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Launch at login" bezelStyle="regularSquare" imagePosition="left" inset="2" id="3gA-J8-849">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="loginButtonPressed:" target="Voe-Tx-rLC" id="rb1-Gh-rcU"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="nf3-YB-f25">
|
||||
<rect key="frame" x="0.0" y="0.0" width="201" height="360"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" drawsBackground="YES" id="zOz-NV-pht">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<imageView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="kVc-EA-5LL">
|
||||
<rect key="frame" x="46" y="0.0" width="325" height="65"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" animates="YES" imageScaling="proportionallyDown" image="overSight" id="WbC-HV-n62"/>
|
||||
</imageView>
|
||||
<imageView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ks1-o6-l6E">
|
||||
<rect key="frame" x="9" y="169" width="183" height="183"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" animates="YES" imageScaling="proportionallyDown" image="icon" id="Cv4-hx-zrt"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
</view>
|
||||
</window>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="icon" width="512" height="512"/>
|
||||
<image name="overSight" width="1396" height="286"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "512x512",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "512x512",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?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></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>1</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright (c) 2016 Objective-See. All rights reserved.</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,13 @@
|
|||
//
|
||||
// main.m
|
||||
// Test Application
|
||||
//
|
||||
// Created by Patrick Wardle on 9/10/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
return NSApplicationMain(argc, argv);
|
||||
}
|
|
@ -0,0 +1,740 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
7D17C4941D658A790066232A /* AboutWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D17C48C1D658A790066232A /* AboutWindow.xib */; };
|
||||
7D17C4951D658A790066232A /* AboutWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17C48E1D658A790066232A /* AboutWindowController.m */; };
|
||||
7D17C4971D658A790066232A /* Logging.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17C4931D658A790066232A /* Logging.m */; };
|
||||
7D17C5271D6592FE0066232A /* statusIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 7D17C5141D658FEB0066232A /* statusIcon.png */; };
|
||||
7D17C5281D6592FE0066232A /* statusIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 7D17C5151D658FEB0066232A /* statusIcon@2x.png */; };
|
||||
7D17C5391D659E580066232A /* AboutWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D17C52C1D659E580066232A /* AboutWindow.xib */; };
|
||||
7D17C53B1D659E580066232A /* Exception.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17C5311D659E580066232A /* Exception.m */; };
|
||||
7D17C53C1D659E580066232A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 7D17C5331D659E580066232A /* icon.png */; };
|
||||
7D17C53D1D659E580066232A /* overSight.png in Resources */ = {isa = PBXBuildFile; fileRef = 7D17C5341D659E580066232A /* overSight.png */; };
|
||||
7D17C53F1D659E580066232A /* Utilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17C5381D659E580066232A /* Utilities.m */; };
|
||||
7D17CFE41D811B4E0017B475 /* Utilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17C5381D659E580066232A /* Utilities.m */; };
|
||||
7D17CFE51D8133840017B475 /* AVMonitor.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17CFE11D81121E0017B475 /* AVMonitor.m */; };
|
||||
7D17D0101D8136C60017B475 /* OverSightXPC.xpc in Embed XPC Services */ = {isa = PBXBuildFile; fileRef = 7DC9C8121D641A350017D143 /* OverSightXPC.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
7D62457C1D84FB8900870565 /* Enumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D62457B1D84FB8900870565 /* Enumerator.m */; };
|
||||
7D62457D1D8517F500870565 /* Logging.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17C4931D658A790066232A /* Logging.m */; };
|
||||
7D6245801D85348E00870565 /* Utilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D62457F1D85348E00870565 /* Utilities.m */; };
|
||||
7D6245811D8537CF00870565 /* Logging.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17C4931D658A790066232A /* Logging.m */; };
|
||||
7DAF4B7F1D657192000DA31A /* StatusBarMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DAF4B7D1D656FD3000DA31A /* StatusBarMenu.m */; };
|
||||
7DC9C8171D641A350017D143 /* OverSightXPC.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DC9C8161D641A350017D143 /* OverSightXPC.m */; };
|
||||
7DC9C8191D641A350017D143 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DC9C8181D641A350017D143 /* main.m */; };
|
||||
7DC9C81D1D641A350017D143 /* OverSightXPC.xpc in Embed XPC Services */ = {isa = PBXBuildFile; fileRef = 7DC9C8121D641A350017D143 /* OverSightXPC.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
8B5755A119DA3E9500799E6B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B5755A019DA3E9500799E6B /* main.m */; };
|
||||
8B5755A419DA3E9500799E6B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B5755A319DA3E9500799E6B /* AppDelegate.m */; };
|
||||
8B5755A619DA3E9500799E6B /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8B5755A519DA3E9500799E6B /* Images.xcassets */; };
|
||||
8B5755A919DA3E9500799E6B /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8B5755A719DA3E9500799E6B /* MainMenu.xib */; };
|
||||
8B5755C719DA3F9300799E6B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B5755C619DA3F9300799E6B /* main.m */; };
|
||||
8B5755CA19DA3F9300799E6B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B5755C919DA3F9300799E6B /* AppDelegate.m */; };
|
||||
8B5755CC19DA3F9300799E6B /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8B5755CB19DA3F9300799E6B /* Images.xcassets */; };
|
||||
8B5755CF19DA3F9300799E6B /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8B5755CD19DA3F9300799E6B /* MainMenu.xib */; };
|
||||
8B5755E319DA41D300799E6B /* ServiceManagement.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B5755E219DA41D300799E6B /* ServiceManagement.framework */; };
|
||||
8B5755E619DA432000799E6B /* OverSight Helper.app in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8B5755C219DA3F9300799E6B /* OverSight Helper.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
7D17CFE61D81349D0017B475 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 8B57559319DA3E9500799E6B /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 7DC9C8111D641A350017D143;
|
||||
remoteInfo = OverSightXPC;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
7D17D00B1D81369C0017B475 /* Embed XPC Services */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "$(CONTENTS_FOLDER_PATH)/XPCServices";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
7D17D0101D8136C60017B475 /* OverSightXPC.xpc in Embed XPC Services */,
|
||||
);
|
||||
name = "Embed XPC Services";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
7DC9C8211D641A350017D143 /* Embed XPC Services */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "$(CONTENTS_FOLDER_PATH)/XPCServices";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
7DC9C81D1D641A350017D143 /* OverSightXPC.xpc in Embed XPC Services */,
|
||||
);
|
||||
name = "Embed XPC Services";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8B5755E519DA42C100799E6B /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = Contents/Library/LoginItems;
|
||||
dstSubfolderSpec = 1;
|
||||
files = (
|
||||
8B5755E619DA432000799E6B /* OverSight Helper.app in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
7D17C48C1D658A790066232A /* AboutWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = AboutWindow.xib; path = Shared/AboutWindow.xib; sourceTree = SOURCE_ROOT; };
|
||||
7D17C48D1D658A790066232A /* AboutWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AboutWindowController.h; path = Shared/AboutWindowController.h; sourceTree = SOURCE_ROOT; };
|
||||
7D17C48E1D658A790066232A /* AboutWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AboutWindowController.m; path = Shared/AboutWindowController.m; sourceTree = SOURCE_ROOT; };
|
||||
7D17C48F1D658A790066232A /* Consts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Consts.h; path = Shared/Consts.h; sourceTree = SOURCE_ROOT; };
|
||||
7D17C4901D658A790066232A /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Exception.h; path = Shared/Exception.h; sourceTree = SOURCE_ROOT; };
|
||||
7D17C4911D658A790066232A /* Exception.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Exception.m; path = Shared/Exception.m; sourceTree = SOURCE_ROOT; };
|
||||
7D17C4921D658A790066232A /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = Shared/Logging.h; sourceTree = SOURCE_ROOT; };
|
||||
7D17C4931D658A790066232A /* Logging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Logging.m; path = Shared/Logging.m; sourceTree = SOURCE_ROOT; };
|
||||
7D17C5141D658FEB0066232A /* statusIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = statusIcon.png; path = Images/statusIcon.png; sourceTree = "<group>"; };
|
||||
7D17C5151D658FEB0066232A /* statusIcon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "statusIcon@2x.png"; path = "Images/statusIcon@2x.png"; sourceTree = "<group>"; };
|
||||
7D17C52C1D659E580066232A /* AboutWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AboutWindow.xib; sourceTree = "<group>"; };
|
||||
7D17C52D1D659E580066232A /* AboutWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AboutWindowController.h; sourceTree = "<group>"; };
|
||||
7D17C52E1D659E580066232A /* AboutWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AboutWindowController.m; sourceTree = "<group>"; };
|
||||
7D17C52F1D659E580066232A /* Consts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Consts.h; sourceTree = "<group>"; };
|
||||
7D17C5301D659E580066232A /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = "<group>"; };
|
||||
7D17C5311D659E580066232A /* Exception.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Exception.m; sourceTree = "<group>"; };
|
||||
7D17C5331D659E580066232A /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon.png; sourceTree = "<group>"; };
|
||||
7D17C5341D659E580066232A /* overSight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = overSight.png; sourceTree = "<group>"; };
|
||||
7D17C5351D659E580066232A /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Logging.h; sourceTree = "<group>"; };
|
||||
7D17C5361D659E580066232A /* Logging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Logging.m; sourceTree = "<group>"; };
|
||||
7D17C5371D659E580066232A /* Utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utilities.h; sourceTree = "<group>"; };
|
||||
7D17C5381D659E580066232A /* Utilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Utilities.m; sourceTree = "<group>"; };
|
||||
7D17CFDE1D810D6D0017B475 /* XPCProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPCProtocol.h; path = Shared/XPCProtocol.h; sourceTree = SOURCE_ROOT; };
|
||||
7D17CFE11D81121E0017B475 /* AVMonitor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AVMonitor.m; sourceTree = "<group>"; };
|
||||
7D17CFE21D81121E0017B475 /* AVMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AVMonitor.h; sourceTree = "<group>"; };
|
||||
7D62457A1D84FB8900870565 /* Enumerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Enumerator.h; sourceTree = "<group>"; };
|
||||
7D62457B1D84FB8900870565 /* Enumerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Enumerator.m; sourceTree = "<group>"; };
|
||||
7D62457E1D85348E00870565 /* Utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utilities.h; sourceTree = "<group>"; };
|
||||
7D62457F1D85348E00870565 /* Utilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Utilities.m; sourceTree = "<group>"; };
|
||||
7DAF4B7C1D656FD3000DA31A /* StatusBarMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StatusBarMenu.h; sourceTree = "<group>"; };
|
||||
7DAF4B7D1D656FD3000DA31A /* StatusBarMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StatusBarMenu.m; sourceTree = "<group>"; };
|
||||
7DC9C8121D641A350017D143 /* OverSightXPC.xpc */ = {isa = PBXFileReference; explicitFileType = "wrapper.xpc-service"; includeInIndex = 0; path = OverSightXPC.xpc; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
7DC9C8151D641A350017D143 /* OverSightXPC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OverSightXPC.h; sourceTree = "<group>"; };
|
||||
7DC9C8161D641A350017D143 /* OverSightXPC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OverSightXPC.m; sourceTree = "<group>"; };
|
||||
7DC9C8181D641A350017D143 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
7DC9C81A1D641A350017D143 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
8B57559B19DA3E9500799E6B /* OverSight.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OverSight.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8B57559F19DA3E9500799E6B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
8B5755A019DA3E9500799E6B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
8B5755A219DA3E9500799E6B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
8B5755A319DA3E9500799E6B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
8B5755A519DA3E9500799E6B /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
|
||||
8B5755A819DA3E9500799E6B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
8B5755C219DA3F9300799E6B /* OverSight Helper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "OverSight Helper.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8B5755C519DA3F9300799E6B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
8B5755C619DA3F9300799E6B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
8B5755C819DA3F9300799E6B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
8B5755C919DA3F9300799E6B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
8B5755CB19DA3F9300799E6B /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
|
||||
8B5755CE19DA3F9300799E6B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
8B5755E219DA41D300799E6B /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
7DC9C80F1D641A350017D143 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8B57559819DA3E9500799E6B /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8B5755E319DA41D300799E6B /* ServiceManagement.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8B5755BF19DA3F9300799E6B /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
7D17C48B1D658A670066232A /* Shared */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7D17C48C1D658A790066232A /* AboutWindow.xib */,
|
||||
7D17C48D1D658A790066232A /* AboutWindowController.h */,
|
||||
7D17C48E1D658A790066232A /* AboutWindowController.m */,
|
||||
7D17C48F1D658A790066232A /* Consts.h */,
|
||||
7D17C4901D658A790066232A /* Exception.h */,
|
||||
7D17C4911D658A790066232A /* Exception.m */,
|
||||
7D17C4921D658A790066232A /* Logging.h */,
|
||||
7D17C4931D658A790066232A /* Logging.m */,
|
||||
);
|
||||
name = Shared;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7D17C5131D658FE20066232A /* Images */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7D17C5141D658FEB0066232A /* statusIcon.png */,
|
||||
7D17C5151D658FEB0066232A /* statusIcon@2x.png */,
|
||||
);
|
||||
name = Images;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7D17C52B1D659E580066232A /* Shared */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7D17C52C1D659E580066232A /* AboutWindow.xib */,
|
||||
7D17C52D1D659E580066232A /* AboutWindowController.h */,
|
||||
7D17C52E1D659E580066232A /* AboutWindowController.m */,
|
||||
7D17C52F1D659E580066232A /* Consts.h */,
|
||||
7D17C5301D659E580066232A /* Exception.h */,
|
||||
7D17C5311D659E580066232A /* Exception.m */,
|
||||
7D62457E1D85348E00870565 /* Utilities.h */,
|
||||
7D62457F1D85348E00870565 /* Utilities.m */,
|
||||
7D17C5321D659E580066232A /* Images */,
|
||||
7D17C5351D659E580066232A /* Logging.h */,
|
||||
7D17C5361D659E580066232A /* Logging.m */,
|
||||
7D17C5371D659E580066232A /* Utilities.h */,
|
||||
7D17C5381D659E580066232A /* Utilities.m */,
|
||||
);
|
||||
path = Shared;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7D17C5321D659E580066232A /* Images */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7D17C5331D659E580066232A /* icon.png */,
|
||||
7D17C5341D659E580066232A /* overSight.png */,
|
||||
);
|
||||
path = Images;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7DC9C8131D641A350017D143 /* OverSightXPC */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7D62457A1D84FB8900870565 /* Enumerator.h */,
|
||||
7D62457B1D84FB8900870565 /* Enumerator.m */,
|
||||
7D17CFDE1D810D6D0017B475 /* XPCProtocol.h */,
|
||||
7DC9C8151D641A350017D143 /* OverSightXPC.h */,
|
||||
7DC9C8161D641A350017D143 /* OverSightXPC.m */,
|
||||
7DC9C8181D641A350017D143 /* main.m */,
|
||||
7DC9C81A1D641A350017D143 /* Info.plist */,
|
||||
);
|
||||
path = OverSightXPC;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8B57559219DA3E9500799E6B = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7D17C52B1D659E580066232A /* Shared */,
|
||||
8B5755E219DA41D300799E6B /* ServiceManagement.framework */,
|
||||
8B57559D19DA3E9500799E6B /* MainApp */,
|
||||
8B5755C319DA3F9300799E6B /* LoginItem */,
|
||||
7DC9C8131D641A350017D143 /* OverSightXPC */,
|
||||
8B57559C19DA3E9500799E6B /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8B57559C19DA3E9500799E6B /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8B57559B19DA3E9500799E6B /* OverSight.app */,
|
||||
8B5755C219DA3F9300799E6B /* OverSight Helper.app */,
|
||||
7DC9C8121D641A350017D143 /* OverSightXPC.xpc */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8B57559D19DA3E9500799E6B /* MainApp */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8B5755A219DA3E9500799E6B /* AppDelegate.h */,
|
||||
8B5755A319DA3E9500799E6B /* AppDelegate.m */,
|
||||
8B5755A519DA3E9500799E6B /* Images.xcassets */,
|
||||
8B5755A719DA3E9500799E6B /* MainMenu.xib */,
|
||||
8B57559E19DA3E9500799E6B /* Supporting Files */,
|
||||
);
|
||||
path = MainApp;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8B57559E19DA3E9500799E6B /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8B57559F19DA3E9500799E6B /* Info.plist */,
|
||||
8B5755A019DA3E9500799E6B /* main.m */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8B5755C319DA3F9300799E6B /* LoginItem */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7D17C5131D658FE20066232A /* Images */,
|
||||
7D17C48B1D658A670066232A /* Shared */,
|
||||
7DAF4B7C1D656FD3000DA31A /* StatusBarMenu.h */,
|
||||
7DAF4B7D1D656FD3000DA31A /* StatusBarMenu.m */,
|
||||
8B5755C819DA3F9300799E6B /* AppDelegate.h */,
|
||||
8B5755C919DA3F9300799E6B /* AppDelegate.m */,
|
||||
7D17CFE11D81121E0017B475 /* AVMonitor.m */,
|
||||
7D17CFE21D81121E0017B475 /* AVMonitor.h */,
|
||||
8B5755CB19DA3F9300799E6B /* Images.xcassets */,
|
||||
8B5755CD19DA3F9300799E6B /* MainMenu.xib */,
|
||||
8B5755C419DA3F9300799E6B /* Supporting Files */,
|
||||
);
|
||||
path = LoginItem;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8B5755C419DA3F9300799E6B /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8B5755C519DA3F9300799E6B /* Info.plist */,
|
||||
8B5755C619DA3F9300799E6B /* main.m */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
7DC9C8111D641A350017D143 /* OverSightXPC */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 7DC9C81E1D641A350017D143 /* Build configuration list for PBXNativeTarget "OverSightXPC" */;
|
||||
buildPhases = (
|
||||
7DC9C80E1D641A350017D143 /* Sources */,
|
||||
7DC9C80F1D641A350017D143 /* Frameworks */,
|
||||
7DC9C8101D641A350017D143 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = OverSightXPC;
|
||||
productName = OverSightXPC;
|
||||
productReference = 7DC9C8121D641A350017D143 /* OverSightXPC.xpc */;
|
||||
productType = "com.apple.product-type.xpc-service";
|
||||
};
|
||||
8B57559A19DA3E9500799E6B /* OverSight */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 8B5755B819DA3E9500799E6B /* Build configuration list for PBXNativeTarget "OverSight" */;
|
||||
buildPhases = (
|
||||
8B57559719DA3E9500799E6B /* Sources */,
|
||||
8B57559819DA3E9500799E6B /* Frameworks */,
|
||||
8B57559919DA3E9500799E6B /* Resources */,
|
||||
8B5755E519DA42C100799E6B /* CopyFiles */,
|
||||
7DC9C8211D641A350017D143 /* Embed XPC Services */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = OverSight;
|
||||
productName = "Test Application";
|
||||
productReference = 8B57559B19DA3E9500799E6B /* OverSight.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
8B5755C119DA3F9300799E6B /* OverSight Helper */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 8B5755DC19DA3F9300799E6B /* Build configuration list for PBXNativeTarget "OverSight Helper" */;
|
||||
buildPhases = (
|
||||
8B5755BE19DA3F9300799E6B /* Sources */,
|
||||
8B5755BF19DA3F9300799E6B /* Frameworks */,
|
||||
8B5755C019DA3F9300799E6B /* Resources */,
|
||||
7D17D00B1D81369C0017B475 /* Embed XPC Services */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
7D17CFE71D81349D0017B475 /* PBXTargetDependency */,
|
||||
);
|
||||
name = "OverSight Helper";
|
||||
productName = "Test Application Helper";
|
||||
productReference = 8B5755C219DA3F9300799E6B /* OverSight Helper.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
8B57559319DA3E9500799E6B /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0730;
|
||||
ORGANIZATIONNAME = "Cory Bohon";
|
||||
TargetAttributes = {
|
||||
7DC9C8111D641A350017D143 = {
|
||||
CreatedOnToolsVersion = 7.3.1;
|
||||
DevelopmentTeam = VBG97UB4TA;
|
||||
};
|
||||
8B57559A19DA3E9500799E6B = {
|
||||
CreatedOnToolsVersion = 6.0.1;
|
||||
DevelopmentTeam = VBG97UB4TA;
|
||||
SystemCapabilities = {
|
||||
com.apple.Sandbox = {
|
||||
enabled = 0;
|
||||
};
|
||||
};
|
||||
};
|
||||
8B5755C119DA3F9300799E6B = {
|
||||
CreatedOnToolsVersion = 6.0.1;
|
||||
DevelopmentTeam = VBG97UB4TA;
|
||||
SystemCapabilities = {
|
||||
com.apple.Sandbox = {
|
||||
enabled = 0;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 8B57559619DA3E9500799E6B /* Build configuration list for PBXProject "OverSight" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 8B57559219DA3E9500799E6B;
|
||||
productRefGroup = 8B57559C19DA3E9500799E6B /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
8B57559A19DA3E9500799E6B /* OverSight */,
|
||||
8B5755C119DA3F9300799E6B /* OverSight Helper */,
|
||||
7DC9C8111D641A350017D143 /* OverSightXPC */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
7DC9C8101D641A350017D143 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8B57559919DA3E9500799E6B /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8B5755A619DA3E9500799E6B /* Images.xcassets in Resources */,
|
||||
7D17C53C1D659E580066232A /* icon.png in Resources */,
|
||||
8B5755A919DA3E9500799E6B /* MainMenu.xib in Resources */,
|
||||
7D17C53D1D659E580066232A /* overSight.png in Resources */,
|
||||
7D17C4941D658A790066232A /* AboutWindow.xib in Resources */,
|
||||
7D17C5391D659E580066232A /* AboutWindow.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8B5755C019DA3F9300799E6B /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
7D17C5271D6592FE0066232A /* statusIcon.png in Resources */,
|
||||
7D17C5281D6592FE0066232A /* statusIcon@2x.png in Resources */,
|
||||
8B5755CC19DA3F9300799E6B /* Images.xcassets in Resources */,
|
||||
8B5755CF19DA3F9300799E6B /* MainMenu.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
7DC9C80E1D641A350017D143 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
7D6245811D8537CF00870565 /* Logging.m in Sources */,
|
||||
7D17CFE41D811B4E0017B475 /* Utilities.m in Sources */,
|
||||
7D62457C1D84FB8900870565 /* Enumerator.m in Sources */,
|
||||
7DC9C8191D641A350017D143 /* main.m in Sources */,
|
||||
7DC9C8171D641A350017D143 /* OverSightXPC.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8B57559719DA3E9500799E6B /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8B5755A419DA3E9500799E6B /* AppDelegate.m in Sources */,
|
||||
8B5755A119DA3E9500799E6B /* main.m in Sources */,
|
||||
7D17C4971D658A790066232A /* Logging.m in Sources */,
|
||||
7D17C53B1D659E580066232A /* Exception.m in Sources */,
|
||||
7D17C53F1D659E580066232A /* Utilities.m in Sources */,
|
||||
7D17C4951D658A790066232A /* AboutWindowController.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8B5755BE19DA3F9300799E6B /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
7D6245801D85348E00870565 /* Utilities.m in Sources */,
|
||||
7D62457D1D8517F500870565 /* Logging.m in Sources */,
|
||||
7D17CFE51D8133840017B475 /* AVMonitor.m in Sources */,
|
||||
7DAF4B7F1D657192000DA31A /* StatusBarMenu.m in Sources */,
|
||||
8B5755CA19DA3F9300799E6B /* AppDelegate.m in Sources */,
|
||||
8B5755C719DA3F9300799E6B /* main.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
7D17CFE71D81349D0017B475 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 7DC9C8111D641A350017D143 /* OverSightXPC */;
|
||||
targetProxy = 7D17CFE61D81349D0017B475 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
8B5755A719DA3E9500799E6B /* MainMenu.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
8B5755A819DA3E9500799E6B /* Base */,
|
||||
);
|
||||
name = MainMenu.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8B5755CD19DA3F9300799E6B /* MainMenu.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
8B5755CE19DA3F9300799E6B /* Base */,
|
||||
);
|
||||
name = MainMenu.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
7DC9C81F1D641A350017D143 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CODE_SIGN_IDENTITY = "Developer ID Application: Objective-See, LLC (VBG97UB4TA)";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application: Objective-See, LLC (VBG97UB4TA)";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = OverSightXPC/Info.plist;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.objective-see.OverSightXPC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
7DC9C8201D641A350017D143 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CODE_SIGN_IDENTITY = "Developer ID Application: Objective-See, LLC (VBG97UB4TA)";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application: Objective-See, LLC (VBG97UB4TA)";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = OverSightXPC/Info.plist;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.objective-see.OverSightXPC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
8B5755B619DA3E9500799E6B /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
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_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "Developer ID Application: Objective-See, LLC (VBG97UB4TA)";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
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.9;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
8B5755B719DA3E9500799E6B /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
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_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "Developer ID Application: Objective-See, LLC (VBG97UB4TA)";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
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.9;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
8B5755B919DA3E9500799E6B /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "Developer ID Application: Objective-See, LLC (VBG97UB4TA)";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application: Objective-See, LLC (VBG97UB4TA)";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
INFOPLIST_FILE = MainApp/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.objective-see.OverSight";
|
||||
PRODUCT_NAME = OverSight;
|
||||
PROVISIONING_PROFILE = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
8B5755BA19DA3E9500799E6B /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "Developer ID Application: Objective-See, LLC (VBG97UB4TA)";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application: Objective-See, LLC (VBG97UB4TA)";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
INFOPLIST_FILE = MainApp/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.objective-see.OverSight";
|
||||
PRODUCT_NAME = OverSight;
|
||||
PROVISIONING_PROFILE = "";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
8B5755DD19DA3F9300799E6B /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "Developer ID Application: Objective-See, LLC (VBG97UB4TA)";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application: Objective-See, LLC (VBG97UB4TA)";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = LoginItem/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.objective-see.OverSightHelper";
|
||||
PRODUCT_NAME = "OverSight Helper";
|
||||
PROVISIONING_PROFILE = "";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
8B5755DE19DA3F9300799E6B /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "Developer ID Application: Objective-See, LLC (VBG97UB4TA)";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application: Objective-See, LLC (VBG97UB4TA)";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
INFOPLIST_FILE = LoginItem/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.objective-see.OverSightHelper";
|
||||
PRODUCT_NAME = "OverSight Helper";
|
||||
PROVISIONING_PROFILE = "";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
7DC9C81E1D641A350017D143 /* Build configuration list for PBXNativeTarget "OverSightXPC" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
7DC9C81F1D641A350017D143 /* Debug */,
|
||||
7DC9C8201D641A350017D143 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
8B57559619DA3E9500799E6B /* Build configuration list for PBXProject "OverSight" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
8B5755B619DA3E9500799E6B /* Debug */,
|
||||
8B5755B719DA3E9500799E6B /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
8B5755B819DA3E9500799E6B /* Build configuration list for PBXNativeTarget "OverSight" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
8B5755B919DA3E9500799E6B /* Debug */,
|
||||
8B5755BA19DA3E9500799E6B /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
8B5755DC19DA3F9300799E6B /* Build configuration list for PBXNativeTarget "OverSight Helper" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
8B5755DD19DA3F9300799E6B /* Debug */,
|
||||
8B5755DE19DA3F9300799E6B /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 8B57559319DA3E9500799E6B /* Project object */;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:Test Application.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
|
@ -0,0 +1,101 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0730"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8B5755C119DA3F9300799E6B"
|
||||
BuildableName = "OverSight Helper.app"
|
||||
BlueprintName = "OverSight Helper"
|
||||
ReferencedContainer = "container:OverSight.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8B5755D319DA3F9300799E6B"
|
||||
BuildableName = "Test Application HelperTests.xctest"
|
||||
BlueprintName = "Test Application HelperTests"
|
||||
ReferencedContainer = "container:OverSight.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8B5755C119DA3F9300799E6B"
|
||||
BuildableName = "OverSight Helper.app"
|
||||
BlueprintName = "OverSight Helper"
|
||||
ReferencedContainer = "container:OverSight.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8B5755C119DA3F9300799E6B"
|
||||
BuildableName = "OverSight Helper.app"
|
||||
BlueprintName = "OverSight Helper"
|
||||
ReferencedContainer = "container:OverSight.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8B5755C119DA3F9300799E6B"
|
||||
BuildableName = "OverSight Helper.app"
|
||||
BlueprintName = "OverSight Helper"
|
||||
ReferencedContainer = "container:OverSight.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Installer.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:/Users/patrickw/objective-see/OverSight/OverSight.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// Enumerator.h
|
||||
// cameraUsers
|
||||
//
|
||||
// Created by Patrick Wardle on 9/9/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface Enumerator : NSObject
|
||||
|
||||
/* DEFINES */
|
||||
|
||||
//camera assistant daemon on older macs
|
||||
#define VDC_ASSISTANT @"/System/Library/Frameworks/CoreMediaIO.framework/Versions/A/Resources/VDC.plugin/Contents/Resources/VDCAssistant"
|
||||
|
||||
//camera assistant daemon
|
||||
#define APPLE_CAMERA_ASSISTANT @"/Library/CoreMediaIO/Plug-Ins/DAL/AppleCamera.plugin/Contents/Resources/AppleCameraAssistant"
|
||||
|
||||
//lsmp binary
|
||||
#define LSMP @"/usr/bin/lsmp"
|
||||
|
||||
//sample binary
|
||||
#define SAMPLE @"/usr/bin/sample"
|
||||
|
||||
|
||||
/* PROPERTIES */
|
||||
|
||||
//flag indicating video is action
|
||||
@property BOOL videoActive;
|
||||
|
||||
//list of procs that have send Mach msg to *Assistant
|
||||
@property(nonatomic, retain)NSMutableDictionary* machSenders;
|
||||
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//singleton interface
|
||||
+(id)sharedManager;
|
||||
|
||||
//forever, baseline by getting all current procs that have sent a mach msg to *Assistant
|
||||
// ->ensures its only invoke while camera is not in use, so these are all just baselined procs
|
||||
-(void)start;
|
||||
|
||||
//find 'VDCAssistant' or 'AppleCameraAssistant'
|
||||
-(pid_t)findCameraAssistant;
|
||||
|
||||
//enumerate all (recent) process that appear to be using video
|
||||
-(NSMutableArray*)enumVideoProcs;
|
||||
|
||||
//set status of video
|
||||
-(void)updateVideoStatus:(BOOL)isEnabled;
|
||||
|
||||
@end
|
|
@ -0,0 +1,423 @@
|
|||
//
|
||||
// Enumerator.m
|
||||
// cameraUsers
|
||||
//
|
||||
// Created by Patrick Wardle on 9/9/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Enumerator.h"
|
||||
#import "../Shared/Logging.h"
|
||||
#import "../Shared/Utilities.h"
|
||||
|
||||
#import <libproc.h>
|
||||
#import <sys/sysctl.h>
|
||||
|
||||
//ignored mach sender procs
|
||||
// TODO: maybe just ignore apple signed daemons/bg procs!?
|
||||
static NSArray* ignoredProcs = nil;
|
||||
|
||||
@implementation Enumerator
|
||||
|
||||
@synthesize machSenders;
|
||||
@synthesize videoActive;
|
||||
|
||||
//init
|
||||
-(instancetype)init
|
||||
{
|
||||
//init
|
||||
if(self = [super init])
|
||||
{
|
||||
//alloc dictionary
|
||||
machSenders = [NSMutableDictionary dictionary];
|
||||
|
||||
//init ignored procs
|
||||
ignoredProcs = @[
|
||||
@"/sbin/launchd",
|
||||
@"/usr/libexec/lsd",
|
||||
@"/usr/sbin/notifyd",
|
||||
@"/usr/sbin/syslogd",
|
||||
@"/usr/sbin/cfprefsd",
|
||||
@"/usr/libexec/opendirectoryd",
|
||||
@"/usr/libexec/UserEventAgent",
|
||||
@"/System/Library/CoreServices/launchservicesd",
|
||||
@"/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/CVMServer",
|
||||
@"/System/Library/Frameworks/CoreGraphics.framework/Versions/A/Resources/WindowServer",
|
||||
@"/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/Support/coreservicesd",
|
||||
@"/System/Library/Frameworks/VideoToolbox.framework/Versions/A/XPCServices/VTDecoderXPCService.xpc/Contents/MacOS/VTDecoderXPCService"
|
||||
];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
//singleton interface
|
||||
+(id)sharedManager
|
||||
{
|
||||
//instance
|
||||
static Enumerator *sharedEnumerator = nil;
|
||||
|
||||
//once token
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
//init
|
||||
// ->only exec'd once though :)
|
||||
dispatch_once(&onceToken, ^{
|
||||
|
||||
//init
|
||||
sharedEnumerator = [[self alloc] init];
|
||||
|
||||
});
|
||||
|
||||
return sharedEnumerator;
|
||||
}
|
||||
|
||||
//find 'VDCAssistant' or 'AppleCameraAssistant'
|
||||
-(pid_t)findCameraAssistant
|
||||
{
|
||||
//pid of assistant
|
||||
pid_t cameraAssistant = 0;
|
||||
|
||||
//status
|
||||
int status = -1;
|
||||
|
||||
//# of procs
|
||||
int numberOfProcesses = 0;
|
||||
|
||||
//array of pids
|
||||
pid_t* pids = NULL;
|
||||
|
||||
//process path
|
||||
NSString* processPath = nil;
|
||||
|
||||
//get # of procs
|
||||
numberOfProcesses = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
|
||||
|
||||
//alloc buffer for pids
|
||||
pids = calloc(numberOfProcesses, sizeof(pid_t));
|
||||
|
||||
//get list of pids
|
||||
status = proc_listpids(PROC_ALL_PIDS, 0, pids, numberOfProcesses * sizeof(pid_t));
|
||||
if(status < 0)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//iterate over all pids
|
||||
// ->get name for each via helper function
|
||||
for(int i = 0; i < numberOfProcesses; ++i)
|
||||
{
|
||||
//skip blank pids
|
||||
if(0 == pids[i])
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//get name
|
||||
processPath = getProcessPath(pids[i]);
|
||||
if( (nil == processPath) ||
|
||||
(0 == processPath.length) )
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//is 'VDCAssistant'?
|
||||
if(YES == [processPath isEqualToString:VDC_ASSISTANT])
|
||||
{
|
||||
//save
|
||||
cameraAssistant = pids[i];
|
||||
|
||||
//pau
|
||||
break;
|
||||
}
|
||||
|
||||
//is 'AppleCameraAssistant'?
|
||||
else if(YES == [processPath isEqualToString:APPLE_CAMERA_ASSISTANT])
|
||||
{
|
||||
//save
|
||||
cameraAssistant = pids[i];
|
||||
|
||||
//pau
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
//free buffer
|
||||
if(NULL != pids)
|
||||
{
|
||||
//free
|
||||
free(pids);
|
||||
}
|
||||
|
||||
return cameraAssistant;
|
||||
}
|
||||
|
||||
//forever, baseline by getting all current procs that have sent a mach msg to *Assistant
|
||||
// ->ensures its only invoke while camera is not in use, so these are all just baselined procs
|
||||
-(void)start
|
||||
{
|
||||
//baseline forever
|
||||
// ->though logic will skip if video is active
|
||||
while(YES)
|
||||
{
|
||||
//sync baselining
|
||||
@synchronized(self)
|
||||
{
|
||||
//only baseline if video isn't active
|
||||
if(YES != self.videoActive)
|
||||
{
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"baselining mach senders...");
|
||||
|
||||
//enumerate procs that have send mach messages
|
||||
self.machSenders = [self enumMachSenders:[self findCameraAssistant]];
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"baselined mach senders: %@", self.machSenders]);
|
||||
}
|
||||
}
|
||||
|
||||
//nap for a minute
|
||||
[NSThread sleepForTimeInterval:60];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//enumerate all (recent) process that appear to be using video
|
||||
-(NSMutableArray*)enumVideoProcs
|
||||
{
|
||||
//current procs
|
||||
NSMutableArray* videoProcs = nil;
|
||||
|
||||
//mach senders
|
||||
NSMutableDictionary* currentSenders = nil;
|
||||
|
||||
//candidate video procs
|
||||
// ->those that have new mach message
|
||||
NSMutableArray* candidateVideoProcs = nil;
|
||||
|
||||
//pid of camera assistant process
|
||||
pid_t cameraAssistant = 0;
|
||||
|
||||
//alloc
|
||||
candidateVideoProcs = [NSMutableArray array];
|
||||
|
||||
//sync this logic
|
||||
// ->prevent baselining thread from doing anything
|
||||
@synchronized(self)
|
||||
{
|
||||
|
||||
//find 'VDCAssistant' or 'AppleCameraAssistant'
|
||||
cameraAssistant = [self findCameraAssistant];
|
||||
if(0 == cameraAssistant)
|
||||
{
|
||||
//err msg
|
||||
logMsg(LOG_ERR, @"failed to find VDCAssistant/AppleCameraAssistant process");
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//get procs that currrently have sent Mach msg to *Assistant
|
||||
// ->returns dictionary of process id, and number of mach messages
|
||||
currentSenders = [self enumMachSenders:cameraAssistant];
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"current mach senders: %@", currentSenders]);
|
||||
|
||||
//remove any known/existing senders
|
||||
for(NSNumber* processID in currentSenders.allKeys)
|
||||
{
|
||||
//add any candidate procs
|
||||
// ->those that have new mach message
|
||||
if( [currentSenders[processID] intValue] > [self.machSenders[processID] intValue])
|
||||
{
|
||||
//add
|
||||
[candidateVideoProcs addObject:processID];
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
//remove existing ones
|
||||
if( (nil != self.machSenders[processID]) &&
|
||||
([currentSenders[processID] intValue]) <= [self.machSenders[processID] intValue])
|
||||
{
|
||||
//remove
|
||||
[currentSenders removeObjectForKey:processID];
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"candidate video procs: %@", candidateVideoProcs]);
|
||||
|
||||
//save to baseline
|
||||
// TODO: test that this works, esp if cnt goes down!! (facetime battery mode)
|
||||
//[self.machSenders addEntriesFromDictionary:currentSenders];
|
||||
//update
|
||||
self.machSenders = currentSenders;
|
||||
|
||||
//invoke 'sample' to confirm that candidates are using CMIO/video inputs
|
||||
videoProcs = [self sampleCandidates:candidateVideoProcs];
|
||||
|
||||
}//sync
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return videoProcs;
|
||||
}
|
||||
|
||||
//get procs that currrently have sent Mach msg to *Assistant
|
||||
// ->returns dictionary of process id, and number of mach messages
|
||||
-(NSMutableDictionary*)enumMachSenders:(pid_t)cameraAssistant
|
||||
{
|
||||
//senders
|
||||
NSMutableDictionary* senders = nil;
|
||||
|
||||
//results from 'lsmp' cmd
|
||||
NSString* results = nil;
|
||||
|
||||
//substrings
|
||||
NSArray* subStrings = nil;
|
||||
|
||||
//process id
|
||||
NSNumber* processID = nil;
|
||||
|
||||
//alloc
|
||||
senders = [NSMutableDictionary dictionary];
|
||||
|
||||
//exec 'lsmp' w/ pid of camera asssistant to get mach ports
|
||||
results = [[NSString alloc] initWithData:execTask(LSMP, @[@"-p", @(cameraAssistant).stringValue]) encoding:NSUTF8StringEncoding];
|
||||
if( (nil == results) ||
|
||||
(0 == results.length) )
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//parse results
|
||||
// ->looking for (<pid>) process name
|
||||
for(NSString* line in [results componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\n"]])
|
||||
{
|
||||
//skip blank lines
|
||||
if(0 == line.length)
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//parse on '()'
|
||||
// TODO: improve this!
|
||||
subStrings = [line componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"()"]];
|
||||
if(subStrings.count < 3)
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//skip 'unknown' processes
|
||||
// output looks like "(-) Unknown Process"
|
||||
if(YES == [[subStrings objectAtIndex:0x1] isEqualToString:@"-"])
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//extract process id
|
||||
// ->insides '()', so will be second substring
|
||||
processID = @([[subStrings objectAtIndex:0x1] integerValue]);
|
||||
if(nil == processID)
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//ignore self
|
||||
if(cameraAssistant == processID.intValue)
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//ignore apple daemons (that send mach messages, etc)
|
||||
if(YES == [ignoredProcs containsObject:getProcessPath(processID.intValue)])
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//add/inc to dictionary
|
||||
senders[processID] = @([senders[processID] unsignedIntegerValue] + 1);
|
||||
}
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return senders;
|
||||
}
|
||||
|
||||
//invoke 'sample' to confirm candidates are using CMIO/video inputs
|
||||
-(NSMutableArray*)sampleCandidates:(NSArray*)currentSenders
|
||||
{
|
||||
//current procs
|
||||
NSMutableArray* videoProcs = nil;
|
||||
|
||||
//results from 'sample' cmd
|
||||
NSString* results = nil;
|
||||
|
||||
//alloc
|
||||
videoProcs = [NSMutableArray array];
|
||||
|
||||
//invoke 'sample' on each
|
||||
// TODO: delete tmp file? 'Sample analysis of process 37370 written to file /tmp/FaceTime_2016-09-10_081703_TAwB.sample.txt' (written 2 std err?)
|
||||
for(NSNumber* processID in currentSenders)
|
||||
{
|
||||
//exec 'sample' to get threads/dylibs
|
||||
results = [[NSString alloc] initWithData:execTask(SAMPLE, @[processID.stringValue, @"1"]) encoding:NSUTF8StringEncoding];
|
||||
if( (nil == results) ||
|
||||
(0 == results.length) )
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//for now, just check for 'CMIOGraph::DoWork'
|
||||
// TODO: could look for dylibs, other calls, etc
|
||||
if(YES != [results containsString:@"CMIOGraph::DoWork"])
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//looks like a video proc!
|
||||
[videoProcs addObject:processID];
|
||||
}
|
||||
|
||||
return videoProcs;
|
||||
}
|
||||
|
||||
//set status of video
|
||||
-(void)updateVideoStatus:(BOOL)isEnabled
|
||||
{
|
||||
//sync
|
||||
@synchronized(self)
|
||||
{
|
||||
//set
|
||||
self.videoActive = isEnabled;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?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>CFBundleDisplayName</key>
|
||||
<string>OverSightXPC</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</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>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright (c) 2016 Objective-See. All rights reserved.</string>
|
||||
<key>XPCService</key>
|
||||
<dict>
|
||||
<key>ServiceType</key>
|
||||
<string>Application</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,26 @@
|
|||
//
|
||||
// OverSightXPC.h
|
||||
// OverSightXPC
|
||||
//
|
||||
// Created by Patrick Wardle on 8/16/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "../Shared/XPCProtocol.h"
|
||||
|
||||
/* DEFINES */
|
||||
|
||||
|
||||
// This object implements the protocol which we have defined. It provides the actual behavior for the service. It is 'exported' by the service to make it available to the process hosting the service over an NSXPCConnection.
|
||||
@interface OverSightXPC : NSObject <XPCProtocol>
|
||||
|
||||
/* PROPERTIES */
|
||||
|
||||
//flag indicating video is action
|
||||
@property BOOL videoActive;
|
||||
|
||||
//list of procs that have send Mach msg to *Assistant
|
||||
@property(nonatomic, retain)NSMutableDictionary* machSenders;
|
||||
|
||||
@end
|
|
@ -0,0 +1,93 @@
|
|||
//
|
||||
// OverSightXPC.m
|
||||
// OverSightXPC
|
||||
//
|
||||
// Created by Patrick Wardle on 8/16/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Logging.h"
|
||||
#import "Enumerator.h"
|
||||
#import "OverSightXPC.h"
|
||||
|
||||
|
||||
#import "../Shared/Utilities.h"
|
||||
|
||||
|
||||
|
||||
@implementation OverSightXPC
|
||||
|
||||
//TODO: method to set flag, that's sync'd~!?
|
||||
|
||||
@synthesize machSenders;
|
||||
@synthesize videoActive;
|
||||
|
||||
//do any initializations
|
||||
// ->for now, just kick off enumerator
|
||||
-(void)initialize:(void (^)(void))reply
|
||||
{
|
||||
//start enumerating
|
||||
// ->will forever baseline current mach msg procs
|
||||
[NSThread detachNewThreadSelector:@selector(start) toTarget:[Enumerator sharedManager] withObject:nil];
|
||||
|
||||
//reply
|
||||
reply();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//call into emumerate to get (new) video proc
|
||||
-(void)getVideoProcs:(void (^)(NSMutableArray *))reply
|
||||
{
|
||||
//reply w/ video procs
|
||||
reply([[Enumerator sharedManager] enumVideoProcs]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//update status video
|
||||
// ->allows enumerator to stop baselining (when active), etc
|
||||
-(void)updateVideoStatus:(unsigned int)status reply:(void (^)(void))reply
|
||||
{
|
||||
//set status
|
||||
[[Enumerator sharedManager] updateVideoStatus:status];
|
||||
|
||||
//reply
|
||||
reply();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//kill a process
|
||||
-(void)killProcess:(NSNumber*)processID reply:(void (^)(BOOL))reply
|
||||
{
|
||||
//flag
|
||||
BOOL wasKilled = NO;
|
||||
|
||||
//terminate
|
||||
if(-1 == kill(processID.intValue, SIGKILL))
|
||||
{
|
||||
//err msg
|
||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to kill %@, with %d", processID, errno]);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//happy
|
||||
wasKilled = YES;
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
//reply
|
||||
reply(wasKilled);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
//
|
||||
// main.m
|
||||
// OverSightXPC
|
||||
//
|
||||
// Created by Patrick Wardle on 8/16/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "../Shared/Exception.h"
|
||||
#import "../Shared/XPCProtocol.h"
|
||||
|
||||
#import "OverSightXPC.h"
|
||||
|
||||
//TODO: remove
|
||||
#import <syslog.h>
|
||||
|
||||
//interface for 'extension' to NSXPCConnection
|
||||
// ->allows us to access the 'private' auditToken iVar
|
||||
@interface ExtendedNSXPCConnection : NSXPCConnection
|
||||
{
|
||||
//private iVar
|
||||
audit_token_t auditToken;
|
||||
}
|
||||
//private iVar
|
||||
@property audit_token_t auditToken;
|
||||
|
||||
@end
|
||||
|
||||
//implementation for 'extension' to NSXPCConnection
|
||||
// ->allows us to access the 'private' auditToken iVar
|
||||
@implementation ExtendedNSXPCConnection
|
||||
|
||||
//private iVar
|
||||
@synthesize auditToken;
|
||||
|
||||
@end
|
||||
|
||||
//function def
|
||||
OSStatus SecTaskValidateForRequirement(SecTaskRef task, CFStringRef requirement);
|
||||
|
||||
//signing auth
|
||||
#define SIGNING_AUTH @"Developer ID Application: Objective-See, LLC (VBG97UB4TA)"
|
||||
|
||||
//skeleton interface
|
||||
@interface ServiceDelegate : NSObject <NSXPCListenerDelegate>
|
||||
@end
|
||||
|
||||
@implementation ServiceDelegate
|
||||
|
||||
//automatically invoked
|
||||
//->allows NSXPCListener to configure/accept/resume a new incoming NSXPCConnection
|
||||
// note: we only allow binaries signed by Objective-See to talk to this!
|
||||
-(BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection
|
||||
{
|
||||
//flag
|
||||
BOOL shouldAccept = NO;
|
||||
|
||||
//task ref
|
||||
SecTaskRef taskRef = 0;
|
||||
|
||||
//signing req string
|
||||
NSString *requirementString = nil;
|
||||
|
||||
//init signing req string
|
||||
requirementString = [NSString stringWithFormat:@"anchor trusted and certificate leaf [subject.CN] = \"%@\"", SIGNING_AUTH];
|
||||
|
||||
//step 1: create task ref
|
||||
// ->uses NSXPCConnection's (private) 'auditToken' iVar
|
||||
taskRef = SecTaskCreateWithAuditToken(NULL, ((ExtendedNSXPCConnection*)newConnection).auditToken);
|
||||
if(NULL == taskRef)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//step 2: validate
|
||||
// ->check that client is signed with Objective-See's dev cert
|
||||
if(0 != SecTaskValidateForRequirement(taskRef, (__bridge CFStringRef)(requirementString)))
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//set the interface that the exported object implements
|
||||
newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(XPCProtocol)];
|
||||
|
||||
//set object exported by connection
|
||||
newConnection.exportedObject = [[OverSightXPC alloc] init];
|
||||
|
||||
//resume
|
||||
[newConnection resume];
|
||||
|
||||
//happy
|
||||
shouldAccept = YES;
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
//release task ref object
|
||||
if(NULL != taskRef)
|
||||
{
|
||||
//release
|
||||
CFRelease(taskRef);
|
||||
|
||||
//unset
|
||||
taskRef = NULL;
|
||||
}
|
||||
|
||||
return shouldAccept;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
//main entrypoint
|
||||
// ->install exception handlers & setup/kickoff listener
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
//ret var
|
||||
int status = -1;
|
||||
|
||||
//service delegate
|
||||
ServiceDelegate* delegate = nil;
|
||||
|
||||
//listener
|
||||
NSXPCListener* listener = nil;
|
||||
|
||||
//
|
||||
//first thing...
|
||||
// ->install exception handlers!
|
||||
//TODO: re-enable
|
||||
//installExceptionHandlers();
|
||||
|
||||
/*
|
||||
//TODO: don't think we need this?
|
||||
chown -R root:wheel & chmod -R +s seems to be all thats needed
|
||||
|
||||
//make really r00t
|
||||
// ->needed for exec'ing vmmap, etc
|
||||
if(0 != setuid(0))
|
||||
{
|
||||
//TODO: re-enable
|
||||
//err msg
|
||||
syslog(LOG_ERR, "OBJECTIVE-SEE TASKEXPLORER ERROR: setuid() failed with: %d\n", errno);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
//create the delegate for the service.
|
||||
delegate = [ServiceDelegate new];
|
||||
|
||||
//set up the one NSXPCListener for this service
|
||||
// ->handles incoming connections
|
||||
listener = [NSXPCListener serviceListener];
|
||||
|
||||
//set delegate
|
||||
listener.delegate = delegate;
|
||||
|
||||
//resuming the listener starts this service
|
||||
// ->method does not return
|
||||
[listener resume];
|
||||
|
||||
//baseline
|
||||
|
||||
|
||||
//happy
|
||||
status = 0;
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return status;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="15G1004" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="AboutWindowController">
|
||||
<connections>
|
||||
<outlet property="versionLabel" destination="OSm-xS-Dmd" id="luW-4O-fYe"/>
|
||||
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" animationBehavior="default" id="F0z-JX-Cv5">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" texturedBackground="YES" unifiedTitleAndToolbar="YES"/>
|
||||
<rect key="contentRect" x="196" y="240" width="422" height="123"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1057"/>
|
||||
<view key="contentView" id="se5-gp-TjO">
|
||||
<rect key="frame" x="0.0" y="0.0" width="422" height="123"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lEv-Wj-6S5">
|
||||
<rect key="frame" x="10" y="12" width="110" height="106"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="icon" id="xKf-GK-m0k"/>
|
||||
</imageView>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Eaf-yA-bbe">
|
||||
<rect key="frame" x="141" y="63" width="180" height="50"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="overSight" id="Ws8-bD-j2R"/>
|
||||
</imageView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OSm-xS-Dmd">
|
||||
<rect key="frame" x="141" y="51" width="182" height="19"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="version:" id="bBK-v0-ypq">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HZZ-Es-mpy">
|
||||
<rect key="frame" x="280" y="11" width="128" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="more info" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="J9x-sM-h9S">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="moreInfo:" target="-2" id="YYW-1b-uJY"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="318" y="246.5"/>
|
||||
</window>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="icon" width="512" height="512"/>
|
||||
<image name="overSight" width="1396" height="286"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// AboutWindowController.h
|
||||
// OverSight
|
||||
//
|
||||
// Created by Patrick Wardle on 7/15/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface AboutWindowController : NSWindowController <NSWindowDelegate>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* PROPERTIES */
|
||||
|
||||
//version label/string
|
||||
@property (weak) IBOutlet NSTextField *versionLabel;
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//invoked when user clicks 'more info' button
|
||||
// ->open KK's webpage
|
||||
- (IBAction)moreInfo:(id)sender;
|
||||
|
||||
@end
|
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
// AboutWindowController.m
|
||||
// OverSight
|
||||
//
|
||||
// Created by Patrick Wardle on 7/15/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Consts.h"
|
||||
#import "Utilities.h"
|
||||
#import "AboutWindowController.h"
|
||||
|
||||
@implementation AboutWindowController
|
||||
|
||||
@synthesize versionLabel;
|
||||
|
||||
//automatically called when nib is loaded
|
||||
// ->center window
|
||||
-(void)awakeFromNib
|
||||
{
|
||||
//center
|
||||
[self.window center];
|
||||
}
|
||||
|
||||
//automatically invoked when window is loaded
|
||||
// ->set to white
|
||||
-(void)windowDidLoad
|
||||
{
|
||||
//super
|
||||
[super windowDidLoad];
|
||||
|
||||
//make white
|
||||
[self.window setBackgroundColor: NSColor.whiteColor];
|
||||
|
||||
//set version sting
|
||||
[self.versionLabel setStringValue:[NSString stringWithFormat:@"version: %@", getAppVersion()]];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//automatically invoked when user clicks 'more info'
|
||||
// ->load products webpage view their default browser
|
||||
-(IBAction)moreInfo:(id)sender
|
||||
{
|
||||
//open URL
|
||||
// ->invokes user's default browser
|
||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:PRODUCT_URL]];
|
||||
|
||||
return;
|
||||
}
|
||||
@end
|
|
@ -0,0 +1,107 @@
|
|||
//
|
||||
// Consts.h
|
||||
// WhatsYourSign
|
||||
//
|
||||
// Created by Patrick Wardle on 7/7/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
//TODO: update!
|
||||
|
||||
#ifndef WYS_Consts_h
|
||||
#define WYS_Consts_h
|
||||
|
||||
//success
|
||||
#define STATUS_SUCCESS 0
|
||||
|
||||
//product url
|
||||
#define PRODUCT_URL @"https://objective-see.com/products/whatsyoursign.html"
|
||||
|
||||
//installed extensions
|
||||
#define INSTALLED_EXTENSIONS @"~/Library/Preferences/com.apple.preferences.extensions.FinderSync.plist"
|
||||
|
||||
//bundle ID of finder sync extension
|
||||
#define EXTENSION_BUNDLE_ID @"com.objective-see.WhatsYourSignExt.FinderSync"
|
||||
|
||||
//extension folder
|
||||
#define EXTENSION_FOLDER @"~/Library/WhatsYourSign"
|
||||
|
||||
//extension name
|
||||
#define EXTENSION_NAME @"WhatsYourSign.appex"
|
||||
|
||||
//frame shift
|
||||
// ->for status msg to avoid activity indicator
|
||||
#define FRAME_SHIFT 45
|
||||
|
||||
//hotkey 'w'
|
||||
#define KEYCODE_W 0xD
|
||||
|
||||
//hotkey 'q'
|
||||
#define KEYCODE_Q 0xC
|
||||
|
||||
//signature status
|
||||
#define KEY_SIGNATURE_STATUS @"signatureStatus"
|
||||
|
||||
//signing auths
|
||||
#define KEY_SIGNING_AUTHORITIES @"signingAuthorities"
|
||||
|
||||
//file belongs to apple?
|
||||
#define KEY_SIGNING_IS_APPLE @"signedByApple"
|
||||
|
||||
//file signed with apple dev id
|
||||
#define KEY_SIGNING_IS_APPLE_DEV_ID @"signedWithDevID"
|
||||
|
||||
//from app store
|
||||
#define KEY_SIGNING_IS_APP_STORE @"fromAppStore"
|
||||
|
||||
//OS version x
|
||||
#define OS_MAJOR_VERSION_X 10
|
||||
|
||||
//OS minor version yosemite
|
||||
#define OS_MINOR_VERSION_YOSEMITE 10
|
||||
|
||||
//OS minor version el capitan
|
||||
#define OS_MINOR_VERSION_EL_CAPITAN 11
|
||||
|
||||
//path to file binary
|
||||
#define FILE @"/usr/bin/file"
|
||||
|
||||
//path to pluginkit binary
|
||||
#define PLUGIN_KIT @"/usr/bin/pluginkit"
|
||||
|
||||
//path to pkgutil
|
||||
#define PKG_UTIL @"/usr/sbin/pkgutil"
|
||||
|
||||
//action to install
|
||||
// ->also button title
|
||||
#define ACTION_INSTALL @"Install"
|
||||
|
||||
//action to uninstall
|
||||
// ->also button title
|
||||
#define ACTION_UNINSTALL @"Uninstall"
|
||||
|
||||
//flag to uninstall
|
||||
#define ACTION_UNINSTALL_FLAG 0
|
||||
|
||||
//flag to install
|
||||
#define ACTION_INSTALL_FLAG 1
|
||||
|
||||
//error msg
|
||||
#define KEY_ERROR_MSG @"errorMsg"
|
||||
|
||||
//sub msg
|
||||
#define KEY_ERROR_SUB_MSG @"errorSubMsg"
|
||||
|
||||
//error URL
|
||||
#define KEY_ERROR_URL @"errorURL"
|
||||
|
||||
//flag for error popup
|
||||
#define KEY_ERROR_SHOULD_EXIT @"shouldExit"
|
||||
|
||||
//errors url
|
||||
#define ERRORS_URL @"https://objective-see.com/errors.html"
|
||||
|
||||
//general error URL
|
||||
#define FATAL_ERROR_URL @"https://objective-see.com/errors.html"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// Exception.h
|
||||
// WhatsYourSign
|
||||
//
|
||||
// Created by Patrick Wardle on 7/7/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
#import <signal.h>
|
||||
|
||||
//install exception/signal handlers
|
||||
void installExceptionHandlers();
|
||||
|
||||
//exception handler for Obj-C exceptions
|
||||
void exceptionHandler(NSException *exception);
|
||||
|
||||
//signal handler for *nix style exceptions
|
||||
void signalHandler(int signal, siginfo_t *info, void *context);
|
||||
|
||||
//display error window
|
||||
void displayErrorWindow(NSDictionary* errorInfo);
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,190 @@
|
|||
//
|
||||
// Exception.m
|
||||
// WhatsYourSign
|
||||
//
|
||||
// Created by Patrick Wardle on 7/7/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Consts.h"
|
||||
#import "Logging.h"
|
||||
#import "Exception.h"
|
||||
#import "Utilities.h"
|
||||
|
||||
//TODO: renenable
|
||||
/*
|
||||
#ifdef IS_INSTALLER_APP
|
||||
#import "AppDelegate.h"
|
||||
#endif
|
||||
*/
|
||||
|
||||
//global
|
||||
// ->only report an fatal exception once
|
||||
BOOL wasReported = NO;
|
||||
|
||||
//install exception/signal handlers
|
||||
void installExceptionHandlers()
|
||||
{
|
||||
//sigaction struct
|
||||
struct sigaction sa = {0};
|
||||
|
||||
//init signal struct
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
sa.sa_sigaction = signalHandler;
|
||||
|
||||
//objective-C exception handler
|
||||
NSSetUncaughtExceptionHandler(&exceptionHandler);
|
||||
|
||||
//install signal handlers
|
||||
sigaction(SIGILL, &sa, NULL);
|
||||
sigaction(SIGSEGV, &sa, NULL);
|
||||
sigaction(SIGBUS, &sa, NULL);
|
||||
sigaction(SIGABRT, &sa, NULL);
|
||||
sigaction(SIGTRAP, &sa, NULL);
|
||||
sigaction(SIGFPE, &sa, NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//exception handler
|
||||
// will be invoked for Obj-C exceptions
|
||||
void exceptionHandler(NSException *exception)
|
||||
{
|
||||
//error msg
|
||||
NSString* errorMessage = nil;
|
||||
|
||||
//ignore if exception was already reported
|
||||
if(YES == wasReported)
|
||||
{
|
||||
//bail
|
||||
return;
|
||||
}
|
||||
|
||||
//err msg
|
||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"OBJECTIVE-SEE ERROR: OS version: %@ /App version: %@", [[NSProcessInfo processInfo] operatingSystemVersionString], getAppVersion()]);
|
||||
|
||||
//create error msg
|
||||
errorMessage = [NSString stringWithFormat:@"unhandled obj-c exception caught [name: %@ / reason: %@]", [exception name], [exception reason]];
|
||||
|
||||
//err msg
|
||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"OBJECTIVE-SEE ERROR: %@", errorMessage]);
|
||||
|
||||
//err msg
|
||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"OBJECTIVE-SEE ERROR: %@", [[NSThread callStackSymbols] description]]);
|
||||
|
||||
//set flag
|
||||
wasReported = YES;
|
||||
|
||||
//start installer-specific code
|
||||
#ifdef IS_INSTALLER_APP
|
||||
|
||||
//error info dictionary
|
||||
NSMutableDictionary* errorInfo = nil;
|
||||
|
||||
//alloc
|
||||
errorInfo = [NSMutableDictionary dictionary];
|
||||
|
||||
//add main error msg
|
||||
errorInfo[KEY_ERROR_MSG] = @"ERROR: unrecoverable fault";
|
||||
|
||||
//add sub msg
|
||||
errorInfo[KEY_ERROR_SUB_MSG] = [exception name];
|
||||
|
||||
//set error URL
|
||||
errorInfo[KEY_ERROR_URL] = FATAL_ERROR_URL;
|
||||
|
||||
//fatal error
|
||||
// ->agent should exit
|
||||
errorInfo[KEY_ERROR_SHOULD_EXIT] = [NSNumber numberWithBool:YES];
|
||||
|
||||
//TODO: renable
|
||||
//display error msg
|
||||
//[((AppDelegate*)[[NSApplication sharedApplication] delegate]) displayErrorWindow:errorInfo];
|
||||
|
||||
//need to sleep, otherwise returning from this function will cause OS to kill agent
|
||||
// ->instead, we want error popup to be displayed (which will exit agent when closed)
|
||||
if(YES != [NSThread isMainThread])
|
||||
{
|
||||
//nap
|
||||
while(YES)
|
||||
{
|
||||
//nap
|
||||
[NSThread sleepForTimeInterval:1.0f];
|
||||
}
|
||||
}
|
||||
|
||||
//end app-specific code
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//handler for signals
|
||||
// will be invoked for BSD/*nix signals
|
||||
void signalHandler(int signal, siginfo_t *info, void *context)
|
||||
{
|
||||
//error msg
|
||||
NSString* errorMessage = nil;
|
||||
|
||||
//context
|
||||
ucontext_t *uContext = NULL;
|
||||
|
||||
//ignore if exception was already reported
|
||||
if(YES == wasReported)
|
||||
{
|
||||
//bail
|
||||
return;
|
||||
}
|
||||
|
||||
//err msg
|
||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"OBJECTIVE-SEE ERROR: OS version: %@ /App version: %@", [[NSProcessInfo processInfo] operatingSystemVersionString], getAppVersion()]);
|
||||
|
||||
//typecast context
|
||||
uContext = (ucontext_t *)context;
|
||||
|
||||
//create error msg
|
||||
errorMessage = [NSString stringWithFormat:@"unhandled exception caught, si_signo: %d /si_code: %s /si_addr: %p /rip: %p",
|
||||
info->si_signo, (info->si_code == SEGV_MAPERR) ? "SEGV_MAPERR" : "SEGV_ACCERR", info->si_addr, (unsigned long*)uContext->uc_mcontext->__ss.__rip];
|
||||
|
||||
//err msg
|
||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"OBJECTIVE-SEE ERROR: %@", errorMessage]);
|
||||
|
||||
//err msg
|
||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"OBJECTIVE-SEE ERROR: %@", [[NSThread callStackSymbols] description]]);
|
||||
|
||||
//set flag
|
||||
wasReported = YES;
|
||||
|
||||
//start installer-specific code
|
||||
#ifdef IS_INSTALLER_APP
|
||||
|
||||
//error info dictionary
|
||||
NSMutableDictionary* errorInfo = nil;
|
||||
|
||||
//alloc
|
||||
errorInfo = [NSMutableDictionary dictionary];
|
||||
|
||||
//add main error msg
|
||||
errorInfo[KEY_ERROR_MSG] = @"ERROR: unrecoverable fault";
|
||||
|
||||
//add sub msg
|
||||
errorInfo[KEY_ERROR_SUB_MSG] = [NSString stringWithFormat:@"si_signo: %d / rip: %p", info->si_signo, (unsigned long*)uContext->uc_mcontext->__ss.__rip];
|
||||
|
||||
//set error URL
|
||||
errorInfo[KEY_ERROR_URL] = FATAL_ERROR_URL;
|
||||
|
||||
//fatal error
|
||||
// ->agent should exit
|
||||
errorInfo[KEY_ERROR_SHOULD_EXIT] = [NSNumber numberWithBool:YES];
|
||||
|
||||
//TODO: renable
|
||||
//display error msg
|
||||
//[((AppDelegate*)[[NSApplication sharedApplication] delegate]) displayErrorWindow:errorInfo];
|
||||
|
||||
//end app-specific code
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 16 KiB |
|
@ -0,0 +1,14 @@
|
|||
//
|
||||
// Logging.h
|
||||
// WhatsYourSign
|
||||
//
|
||||
// Created by Patrick Wardle on 7/7/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
#import <syslog.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
//log a msg to syslog
|
||||
// ->also disk, if error
|
||||
void logMsg(int level, NSString* msg);
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// Logging.m
|
||||
// WhatsYourSign
|
||||
//
|
||||
// Created by Patrick Wardle on 7/7/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Consts.h"
|
||||
#import "Logging.h"
|
||||
#import "Utilities.h"
|
||||
|
||||
//log a msg
|
||||
void logMsg(int level, NSString* msg)
|
||||
{
|
||||
//log prefix
|
||||
NSMutableString* logPrefix = nil;
|
||||
|
||||
//alloc/init
|
||||
logPrefix = [NSMutableString stringWithString:@"OBJECTIVE-SEE OVERSIGHT"];
|
||||
|
||||
//if its error, add error to prefix
|
||||
if(LOG_ERR == level)
|
||||
{
|
||||
//add
|
||||
[logPrefix appendString:@" ERROR"];
|
||||
}
|
||||
|
||||
//debug mode logic
|
||||
#ifdef DEBUG
|
||||
|
||||
//in debug mode promote debug msgs to LOG_NOTICE
|
||||
// ->OS X only shows LOG_NOTICE and above
|
||||
if(LOG_DEBUG == level)
|
||||
{
|
||||
//promote
|
||||
level = LOG_NOTICE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//log to syslog
|
||||
syslog(level, "%s: %s\n", [logPrefix UTF8String], [msg UTF8String]);
|
||||
|
||||
//TODO: remove
|
||||
NSLog(@"%s: %s", [logPrefix UTF8String], [msg UTF8String]);
|
||||
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// Utilities.h
|
||||
// WhatsYourSign
|
||||
//
|
||||
// Created by Patrick Wardle on 7/7/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef WYS_Utilities_h
|
||||
#define WYS_Utilities_h
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/* FUNCTIONS */
|
||||
|
||||
//get app's version
|
||||
// ->extracted from Info.plist
|
||||
NSString* getAppVersion();
|
||||
|
||||
//exec a process and grab it's output
|
||||
NSData* execTask(NSString* binaryPath, NSArray* arguments);
|
||||
|
||||
//get OS's major or minor version
|
||||
SInt32 getVersion(OSType selector);
|
||||
|
||||
//given a path to binary
|
||||
// parse it back up to find app's bundle
|
||||
NSBundle* findAppBundle(NSString* binaryPath);
|
||||
|
||||
//given a directory and a filter predicate
|
||||
// ->return all matches
|
||||
NSArray* directoryContents(NSString* directory, NSString* predicate);
|
||||
|
||||
//hash (sha1/md5) a file
|
||||
NSDictionary* hashFile(NSString* filePath);
|
||||
|
||||
//get app's version
|
||||
// ->extracted from Info.plist
|
||||
NSString* getAppVersion();
|
||||
|
||||
//exec a process and grab it's output
|
||||
NSData* execTask(NSString* binaryPath, NSArray* arguments);
|
||||
|
||||
//get process's path
|
||||
NSString* getProcessPath(pid_t pid);
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,273 @@
|
|||
//
|
||||
// Utilities.m
|
||||
// WhatsYourSign
|
||||
//
|
||||
// Created by Patrick Wardle on 7/7/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Consts.h"
|
||||
#import "Utilities.h"
|
||||
|
||||
#import <signal.h>
|
||||
#import <unistd.h>
|
||||
#import <libproc.h>
|
||||
#import <sys/sysctl.h>
|
||||
#import <Security/Security.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CommonCrypto/CommonDigest.h>
|
||||
#import <SystemConfiguration/SystemConfiguration.h>
|
||||
|
||||
//get app's version
|
||||
// ->extracted from Info.plist
|
||||
NSString* getAppVersion()
|
||||
{
|
||||
//read and return 'CFBundleVersion' from bundle
|
||||
return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
|
||||
}
|
||||
|
||||
//given a path to binary
|
||||
// parse it back up to find app's bundle
|
||||
NSBundle* findAppBundle(NSString* binaryPath)
|
||||
{
|
||||
//app's bundle
|
||||
NSBundle* appBundle = nil;
|
||||
|
||||
//app's path
|
||||
NSString* appPath = nil;
|
||||
|
||||
//first just try full path
|
||||
appPath = binaryPath;
|
||||
|
||||
//try to find the app's bundle/info dictionary
|
||||
do
|
||||
{
|
||||
//try to load app's bundle
|
||||
appBundle = [NSBundle bundleWithPath:appPath];
|
||||
|
||||
//check for match
|
||||
// ->binary path's match
|
||||
if( (nil != appBundle) &&
|
||||
(YES == [appBundle.executablePath isEqualToString:binaryPath]))
|
||||
{
|
||||
//all done
|
||||
break;
|
||||
}
|
||||
|
||||
//always unset bundle var since it's being returned
|
||||
// ->and at this point, its not a match
|
||||
appBundle = nil;
|
||||
|
||||
//remove last part
|
||||
// ->will try this next
|
||||
appPath = [appPath stringByDeletingLastPathComponent];
|
||||
|
||||
//scan until we get to root
|
||||
// ->of course, loop will exit if app info dictionary is found/loaded
|
||||
} while( (nil != appPath) &&
|
||||
(YES != [appPath isEqualToString:@"/"]) &&
|
||||
(YES != [appPath isEqualToString:@""]) );
|
||||
|
||||
return appBundle;
|
||||
}
|
||||
|
||||
//exec a process and grab it's output
|
||||
NSData* execTask(NSString* binaryPath, NSArray* arguments)
|
||||
{
|
||||
//task
|
||||
NSTask *task = nil;
|
||||
|
||||
//output pipe
|
||||
NSPipe *outPipe = nil;
|
||||
|
||||
//read handle
|
||||
NSFileHandle* readHandle = nil;
|
||||
|
||||
//output
|
||||
NSMutableData *output = nil;
|
||||
|
||||
//init task
|
||||
task = [NSTask new];
|
||||
|
||||
//init output pipe
|
||||
outPipe = [NSPipe pipe];
|
||||
|
||||
//init read handle
|
||||
readHandle = [outPipe fileHandleForReading];
|
||||
|
||||
//init output buffer
|
||||
output = [NSMutableData data];
|
||||
|
||||
//set task's path
|
||||
[task setLaunchPath:binaryPath];
|
||||
|
||||
//set task's args
|
||||
[task setArguments:arguments];
|
||||
|
||||
//set task's output
|
||||
[task setStandardOutput:outPipe];
|
||||
|
||||
//wrap task launch
|
||||
@try
|
||||
{
|
||||
//launch
|
||||
[task launch];
|
||||
}
|
||||
@catch(NSException *exception)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//read in output
|
||||
while(YES == [task isRunning])
|
||||
{
|
||||
//accumulate output
|
||||
[output appendData:[readHandle readDataToEndOfFile]];
|
||||
}
|
||||
|
||||
//grab any left over data
|
||||
[output appendData:[readHandle readDataToEndOfFile]];
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
//get OS's major or minor version
|
||||
SInt32 getVersion(OSType selector)
|
||||
{
|
||||
//version
|
||||
// ->major or minor
|
||||
SInt32 version = -1;
|
||||
|
||||
//get version info
|
||||
if(noErr != Gestalt(selector, &version))
|
||||
{
|
||||
//reset version
|
||||
version = -1;
|
||||
|
||||
//err
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
//get process's path
|
||||
NSString* getProcessPath(pid_t pid)
|
||||
{
|
||||
//task path
|
||||
NSString* taskPath = nil;
|
||||
|
||||
//buffer for process path
|
||||
char pathBuffer[PROC_PIDPATHINFO_MAXSIZE] = {0};
|
||||
|
||||
//status
|
||||
int status = -1;
|
||||
|
||||
//'management info base' array
|
||||
int mib[3] = {0};
|
||||
|
||||
//system's size for max args
|
||||
int systemMaxArgs = 0;
|
||||
|
||||
//process's args
|
||||
char* taskArgs = NULL;
|
||||
|
||||
//# of args
|
||||
int numberOfArgs = 0;
|
||||
|
||||
//size of buffers, etc
|
||||
size_t size = 0;
|
||||
|
||||
//reset buffer
|
||||
bzero(pathBuffer, PROC_PIDPATHINFO_MAXSIZE);
|
||||
|
||||
//first attempt to get path via 'proc_pidpath()'
|
||||
status = proc_pidpath(pid, pathBuffer, sizeof(pathBuffer));
|
||||
if(0 != status)
|
||||
{
|
||||
//init task's name
|
||||
taskPath = [NSString stringWithUTF8String:pathBuffer];
|
||||
}
|
||||
//otherwise
|
||||
// ->try via task's args ('KERN_PROCARGS2')
|
||||
else
|
||||
{
|
||||
//init mib
|
||||
// ->want system's size for max args
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_ARGMAX;
|
||||
|
||||
//set size
|
||||
size = sizeof(systemMaxArgs);
|
||||
|
||||
//get system's size for max args
|
||||
if(-1 == sysctl(mib, 2, &systemMaxArgs, &size, NULL, 0))
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//alloc space for args
|
||||
taskArgs = malloc(systemMaxArgs);
|
||||
if(NULL == taskArgs)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//init mib
|
||||
// ->want process args
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROCARGS2;
|
||||
mib[2] = pid;
|
||||
|
||||
//set size
|
||||
size = (size_t)systemMaxArgs;
|
||||
|
||||
//get process's args
|
||||
if(-1 == sysctl(mib, 3, taskArgs, &size, NULL, 0))
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//sanity check
|
||||
// ->ensure buffer is somewhat sane
|
||||
if(size <= sizeof(int))
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//extract number of args
|
||||
// ->at start of buffer
|
||||
memcpy(&numberOfArgs, taskArgs, sizeof(numberOfArgs));
|
||||
|
||||
//extract task's name
|
||||
// ->follows # of args (int) and is NULL-terminated
|
||||
taskPath = [NSString stringWithUTF8String:taskArgs + sizeof(int)];
|
||||
}
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
//free process args
|
||||
if(NULL != taskArgs)
|
||||
{
|
||||
//free
|
||||
free(taskArgs);
|
||||
|
||||
//reset
|
||||
taskArgs = NULL;
|
||||
}
|
||||
|
||||
return taskPath;
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// OverSightXPCProtocol.h
|
||||
// OverSightXPC
|
||||
//
|
||||
// Created by Patrick Wardle on 8/16/16.
|
||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
// The protocol that this service will vend as its API. This header file will also need to be visible to the process hosting the service.
|
||||
@protocol XPCProtocol
|
||||
|
||||
//start enumerator
|
||||
-(void)initialize:(void (^)(void))reply;
|
||||
|
||||
//get (new) video procs
|
||||
-(void)getVideoProcs:(void (^)(NSMutableArray *))reply;
|
||||
|
||||
//update status video
|
||||
// ->allows enumerator to stop baselining (when active), etc
|
||||
-(void)updateVideoStatus:(unsigned int)status reply:(void (^)(void))reply;
|
||||
|
||||
//kill a process
|
||||
-(void)killProcess:(NSNumber*)processID reply:(void (^)(BOOL))reply;
|
||||
|
||||
@end
|