mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-13 21:42:32 +00:00
Reverting back to string based version compare. Using customized comparator based ond Sparkle verison compare
This commit is contained in:
@@ -148,8 +148,8 @@
|
|||||||
4C6F228C19A4AA700012310C /* MPAutotypeDelay.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C6F228B19A4AA700012310C /* MPAutotypeDelay.m */; };
|
4C6F228C19A4AA700012310C /* MPAutotypeDelay.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C6F228B19A4AA700012310C /* MPAutotypeDelay.m */; };
|
||||||
4C701CBC178618A000581B88 /* 12_RemoteTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 4C701CBB178618A000581B88 /* 12_RemoteTemplate.pdf */; };
|
4C701CBC178618A000581B88 /* 12_RemoteTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 4C701CBB178618A000581B88 /* 12_RemoteTemplate.pdf */; };
|
||||||
4C7155D81A10DB6D00979307 /* IconSelection.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C7155DA1A10DB6D00979307 /* IconSelection.xib */; };
|
4C7155D81A10DB6D00979307 /* IconSelection.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C7155DA1A10DB6D00979307 /* IconSelection.xib */; };
|
||||||
4C71BCB42167B75900B4CBDA /* MPTestPluginVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C71BCB32167B75900B4CBDA /* MPTestPluginVersion.m */; };
|
4C71BCB42167B75900B4CBDA /* MPTestPluginVersionComparator.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C71BCB32167B75900B4CBDA /* MPTestPluginVersionComparator.m */; };
|
||||||
4C71BCB72167B79C00B4CBDA /* MPPluginVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C71BCB62167B79C00B4CBDA /* MPPluginVersion.m */; };
|
4C71BCB72167B79C00B4CBDA /* MPPluginVersionComparator.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C71BCB62167B79C00B4CBDA /* MPPluginVersionComparator.m */; };
|
||||||
4C735FC02035FCBF00708D53 /* MPPluginEntryActionContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C735FBF2035FCBF00708D53 /* MPPluginEntryActionContext.m */; };
|
4C735FC02035FCBF00708D53 /* MPPluginEntryActionContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C735FBF2035FCBF00708D53 /* MPPluginEntryActionContext.m */; };
|
||||||
4C73B6F1215E64A7009787F7 /* MPWelcomeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C73B6EF215E64A7009787F7 /* MPWelcomeViewController.m */; };
|
4C73B6F1215E64A7009787F7 /* MPWelcomeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C73B6EF215E64A7009787F7 /* MPWelcomeViewController.m */; };
|
||||||
4C76155C1764C04C0015A1A6 /* GeneralSettings.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C76155E1764C04C0015A1A6 /* GeneralSettings.xib */; };
|
4C76155C1764C04C0015A1A6 /* GeneralSettings.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C76155E1764C04C0015A1A6 /* GeneralSettings.xib */; };
|
||||||
@@ -578,9 +578,9 @@
|
|||||||
4C7155E81A10DB7700979307 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/IconSelection.strings; sourceTree = "<group>"; };
|
4C7155E81A10DB7700979307 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/IconSelection.strings; sourceTree = "<group>"; };
|
||||||
4C7155EA1A10DB7800979307 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/IconSelection.strings; sourceTree = "<group>"; };
|
4C7155EA1A10DB7800979307 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/IconSelection.strings; sourceTree = "<group>"; };
|
||||||
4C7155EC1A10DB7900979307 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/IconSelection.strings; sourceTree = "<group>"; };
|
4C7155EC1A10DB7900979307 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/IconSelection.strings; sourceTree = "<group>"; };
|
||||||
4C71BCB32167B75900B4CBDA /* MPTestPluginVersion.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPTestPluginVersion.m; sourceTree = "<group>"; };
|
4C71BCB32167B75900B4CBDA /* MPTestPluginVersionComparator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPTestPluginVersionComparator.m; sourceTree = "<group>"; };
|
||||||
4C71BCB52167B79C00B4CBDA /* MPPluginVersion.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPPluginVersion.h; sourceTree = "<group>"; };
|
4C71BCB52167B79C00B4CBDA /* MPPluginVersionComparator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPPluginVersionComparator.h; sourceTree = "<group>"; };
|
||||||
4C71BCB62167B79C00B4CBDA /* MPPluginVersion.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPPluginVersion.m; sourceTree = "<group>"; };
|
4C71BCB62167B79C00B4CBDA /* MPPluginVersionComparator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPPluginVersionComparator.m; sourceTree = "<group>"; };
|
||||||
4C735FBE2035FCBF00708D53 /* MPPluginEntryActionContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPPluginEntryActionContext.h; sourceTree = "<group>"; };
|
4C735FBE2035FCBF00708D53 /* MPPluginEntryActionContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPPluginEntryActionContext.h; sourceTree = "<group>"; };
|
||||||
4C735FBF2035FCBF00708D53 /* MPPluginEntryActionContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPPluginEntryActionContext.m; sourceTree = "<group>"; };
|
4C735FBF2035FCBF00708D53 /* MPPluginEntryActionContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPPluginEntryActionContext.m; sourceTree = "<group>"; };
|
||||||
4C73B6EE215E64A7009787F7 /* MPWelcomeViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPWelcomeViewController.h; sourceTree = "<group>"; };
|
4C73B6EE215E64A7009787F7 /* MPWelcomeViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPWelcomeViewController.h; sourceTree = "<group>"; };
|
||||||
@@ -1207,7 +1207,7 @@
|
|||||||
4C6BC65F1A36717E00BDDF3D /* MPDatabaseSearch.m */,
|
4C6BC65F1A36717E00BDDF3D /* MPDatabaseSearch.m */,
|
||||||
4C8030491E2FBAA300133E4C /* MPTestKeyMapper.m */,
|
4C8030491E2FBAA300133E4C /* MPTestKeyMapper.m */,
|
||||||
4C8F0C721FCF1B7A00BE157F /* MPTestPickcharsParser.m */,
|
4C8F0C721FCF1B7A00BE157F /* MPTestPickcharsParser.m */,
|
||||||
4C71BCB32167B75900B4CBDA /* MPTestPluginVersion.m */,
|
4C71BCB32167B75900B4CBDA /* MPTestPluginVersionComparator.m */,
|
||||||
4C45FB1F178E09ED0010007D /* Supporting Files */,
|
4C45FB1F178E09ED0010007D /* Supporting Files */,
|
||||||
);
|
);
|
||||||
path = MacPassTests;
|
path = MacPassTests;
|
||||||
@@ -1684,8 +1684,8 @@
|
|||||||
4C81867C216664C70068DAFB /* MPPluginRepositoryItemVersionInfo.m */,
|
4C81867C216664C70068DAFB /* MPPluginRepositoryItemVersionInfo.m */,
|
||||||
4C735FBE2035FCBF00708D53 /* MPPluginEntryActionContext.h */,
|
4C735FBE2035FCBF00708D53 /* MPPluginEntryActionContext.h */,
|
||||||
4C735FBF2035FCBF00708D53 /* MPPluginEntryActionContext.m */,
|
4C735FBF2035FCBF00708D53 /* MPPluginEntryActionContext.m */,
|
||||||
4C71BCB52167B79C00B4CBDA /* MPPluginVersion.h */,
|
4C71BCB52167B79C00B4CBDA /* MPPluginVersionComparator.h */,
|
||||||
4C71BCB62167B79C00B4CBDA /* MPPluginVersion.m */,
|
4C71BCB62167B79C00B4CBDA /* MPPluginVersionComparator.m */,
|
||||||
);
|
);
|
||||||
name = Plugin;
|
name = Plugin;
|
||||||
path = MacPass;
|
path = MacPass;
|
||||||
@@ -1935,7 +1935,7 @@
|
|||||||
files = (
|
files = (
|
||||||
4C45FB2D178E0BCB0010007D /* MPDatabaseLoading.m in Sources */,
|
4C45FB2D178E0BCB0010007D /* MPDatabaseLoading.m in Sources */,
|
||||||
4C8DEAA21C314D2C00D24C32 /* MPTestAutotypeDelay.m in Sources */,
|
4C8DEAA21C314D2C00D24C32 /* MPTestAutotypeDelay.m in Sources */,
|
||||||
4C71BCB42167B75900B4CBDA /* MPTestPluginVersion.m in Sources */,
|
4C71BCB42167B75900B4CBDA /* MPTestPluginVersionComparator.m in Sources */,
|
||||||
4C8F0C731FCF1B7A00BE157F /* MPTestPickcharsParser.m in Sources */,
|
4C8F0C731FCF1B7A00BE157F /* MPTestPickcharsParser.m in Sources */,
|
||||||
4C45FB30178E0CE20010007D /* MPTestDocument.m in Sources */,
|
4C45FB30178E0CE20010007D /* MPTestDocument.m in Sources */,
|
||||||
4C6BC6601A36717E00BDDF3D /* MPDatabaseSearch.m in Sources */,
|
4C6BC6601A36717E00BDDF3D /* MPDatabaseSearch.m in Sources */,
|
||||||
@@ -2059,7 +2059,7 @@
|
|||||||
4C1FA07B18231900003A3F8C /* MPDocument+Autotype.m in Sources */,
|
4C1FA07B18231900003A3F8C /* MPDocument+Autotype.m in Sources */,
|
||||||
4C4B7EE917A45EC6000234C7 /* MPDatePickingViewController.m in Sources */,
|
4C4B7EE917A45EC6000234C7 /* MPDatePickingViewController.m in Sources */,
|
||||||
4C4B7EEE17A467E1000234C7 /* MPGroupInspectorViewController.m in Sources */,
|
4C4B7EEE17A467E1000234C7 /* MPGroupInspectorViewController.m in Sources */,
|
||||||
4C71BCB72167B79C00B4CBDA /* MPPluginVersion.m in Sources */,
|
4C71BCB72167B79C00B4CBDA /* MPPluginVersionComparator.m in Sources */,
|
||||||
4C7B63721C0CB51F00D7038C /* TTTCryptographyTransformers.m in Sources */,
|
4C7B63721C0CB51F00D7038C /* TTTCryptographyTransformers.m in Sources */,
|
||||||
4C4B7EF317A467FC000234C7 /* MPEntryInspectorViewController.m in Sources */,
|
4C4B7EF317A467FC000234C7 /* MPEntryInspectorViewController.m in Sources */,
|
||||||
4C1BDF2B1E4392640012A3F0 /* MPPluginDataViewController.m in Sources */,
|
4C1BDF2B1E4392640012A3F0 /* MPPluginDataViewController.m in Sources */,
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="13529" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="macosx"/>
|
<deployment identifier="macosx"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13529"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14313.18"/>
|
||||||
<capability name="box content view" minToolsVersion="7.0"/>
|
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
@@ -12,6 +11,7 @@
|
|||||||
<outlet property="addRemovePluginsControl" destination="B9Q-hq-K4N" id="Oqj-Ko-8UR"/>
|
<outlet property="addRemovePluginsControl" destination="B9Q-hq-K4N" id="Oqj-Ko-8UR"/>
|
||||||
<outlet property="fallbackDescriptionTextField" destination="qPL-FR-ky7" id="xCb-ED-NIX"/>
|
<outlet property="fallbackDescriptionTextField" destination="qPL-FR-ky7" id="xCb-ED-NIX"/>
|
||||||
<outlet property="fallbackSettingsView" destination="wIk-iw-Tcz" id="dHl-zW-0aI"/>
|
<outlet property="fallbackSettingsView" destination="wIk-iw-Tcz" id="dHl-zW-0aI"/>
|
||||||
|
<outlet property="forceIncompatiblePluginsCheckButton" destination="XIl-03-JZP" id="Aj4-rc-Ao0"/>
|
||||||
<outlet property="loadInsecurePlugsinCheckButton" destination="CqP-oK-S8k" id="YET-o6-7Cc"/>
|
<outlet property="loadInsecurePlugsinCheckButton" destination="CqP-oK-S8k" id="YET-o6-7Cc"/>
|
||||||
<outlet property="pluginTableView" destination="Ocu-C0-03d" id="jbH-qr-bVT"/>
|
<outlet property="pluginTableView" destination="Ocu-C0-03d" id="jbH-qr-bVT"/>
|
||||||
<outlet property="settingsView" destination="tD5-Na-7XI" id="Pa0-Tt-20U"/>
|
<outlet property="settingsView" destination="tD5-Na-7XI" id="Pa0-Tt-20U"/>
|
||||||
@@ -21,19 +21,19 @@
|
|||||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="Hz6-mo-xeY">
|
<customView translatesAutoresizingMaskIntoConstraints="NO" id="Hz6-mo-xeY">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="520" height="473"/>
|
<rect key="frame" x="0.0" y="0.0" width="600" height="473"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<box borderType="line" title="Box" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="vBs-Ga-aq0">
|
<box borderType="line" title="Box" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="vBs-Ga-aq0">
|
||||||
<rect key="frame" x="175" y="46" width="328" height="351"/>
|
<rect key="frame" x="175" y="46" width="408" height="321"/>
|
||||||
<view key="contentView" id="tD5-Na-7XI">
|
<view key="contentView" id="tD5-Na-7XI">
|
||||||
<rect key="frame" x="1" y="1" width="326" height="349"/>
|
<rect key="frame" x="1" y="1" width="406" height="319"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="wIk-iw-Tcz">
|
<customView translatesAutoresizingMaskIntoConstraints="NO" id="wIk-iw-Tcz">
|
||||||
<rect key="frame" x="20" y="20" width="286" height="309"/>
|
<rect key="frame" x="20" y="20" width="366" height="279"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qPL-FR-ky7">
|
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qPL-FR-ky7">
|
||||||
<rect key="frame" x="18" y="272" width="122" height="17"/>
|
<rect key="frame" x="18" y="242" width="330" height="17"/>
|
||||||
<textFieldCell key="cell" controlSize="mini" sendsActionOnEndEditing="YES" title="Plugin Settings Info" id="OOr-SW-jZb">
|
<textFieldCell key="cell" controlSize="mini" sendsActionOnEndEditing="YES" title="Plugin Settings Info" id="OOr-SW-jZb">
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
</subviews>
|
</subviews>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="qPL-FR-ky7" firstAttribute="top" secondItem="wIk-iw-Tcz" secondAttribute="top" constant="20" symbolic="YES" id="BAH-sF-W03"/>
|
<constraint firstItem="qPL-FR-ky7" firstAttribute="top" secondItem="wIk-iw-Tcz" secondAttribute="top" constant="20" symbolic="YES" id="BAH-sF-W03"/>
|
||||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="qPL-FR-ky7" secondAttribute="trailing" constant="20" symbolic="YES" id="HKa-7h-OiN"/>
|
<constraint firstAttribute="trailing" secondItem="qPL-FR-ky7" secondAttribute="trailing" constant="20" symbolic="YES" id="HKa-7h-OiN"/>
|
||||||
<constraint firstItem="qPL-FR-ky7" firstAttribute="leading" secondItem="wIk-iw-Tcz" secondAttribute="leading" constant="20" symbolic="YES" id="UTY-Lu-pvl"/>
|
<constraint firstItem="qPL-FR-ky7" firstAttribute="leading" secondItem="wIk-iw-Tcz" secondAttribute="leading" constant="20" symbolic="YES" id="UTY-Lu-pvl"/>
|
||||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="qPL-FR-ky7" secondAttribute="bottom" constant="20" symbolic="YES" id="wpb-76-pxa"/>
|
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="qPL-FR-ky7" secondAttribute="bottom" constant="20" symbolic="YES" id="wpb-76-pxa"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
</buttonCell>
|
</buttonCell>
|
||||||
</button>
|
</button>
|
||||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="aoG-FD-ds8">
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="aoG-FD-ds8">
|
||||||
<rect key="frame" x="18" y="403" width="484" height="28"/>
|
<rect key="frame" x="18" y="403" width="564" height="28"/>
|
||||||
<textFieldCell key="cell" controlSize="small" sendsActionOnEndEditing="YES" id="2bX-8S-9XM">
|
<textFieldCell key="cell" controlSize="small" sendsActionOnEndEditing="YES" id="2bX-8S-9XM">
|
||||||
<font key="font" metaFont="smallSystem"/>
|
<font key="font" metaFont="smallSystem"/>
|
||||||
<string key="title">If enabled, Plugins without proper signatures will be allowed to load. Keep in mind, that Plugins have full access to your data! Changes take affect on restart.</string>
|
<string key="title">If enabled, Plugins without proper signatures will be allowed to load. Keep in mind, that Plugins have full access to your data! Changes take affect on restart.</string>
|
||||||
@@ -74,13 +74,13 @@
|
|||||||
</textFieldCell>
|
</textFieldCell>
|
||||||
</textField>
|
</textField>
|
||||||
<scrollView autohidesScrollers="YES" horizontalLineScroll="37" horizontalPageScroll="10" verticalLineScroll="37" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fCk-fL-jU8">
|
<scrollView autohidesScrollers="YES" horizontalLineScroll="37" horizontalPageScroll="10" verticalLineScroll="37" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fCk-fL-jU8">
|
||||||
<rect key="frame" x="20" y="50" width="150" height="345"/>
|
<rect key="frame" x="20" y="50" width="150" height="315"/>
|
||||||
<clipView key="contentView" id="lTL-Q2-k45">
|
<clipView key="contentView" id="lTL-Q2-k45">
|
||||||
<rect key="frame" x="1" y="1" width="148" height="343"/>
|
<rect key="frame" x="1" y="1" width="148" height="313"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnSelection="YES" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="35" rowSizeStyle="automatic" viewBased="YES" id="Ocu-C0-03d">
|
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnSelection="YES" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="35" rowSizeStyle="automatic" viewBased="YES" id="Ocu-C0-03d">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="148" height="343"/>
|
<rect key="frame" x="0.0" y="0.0" width="148" height="313"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<size key="intercellSpacing" width="3" height="2"/>
|
<size key="intercellSpacing" width="3" height="2"/>
|
||||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
@@ -154,7 +154,7 @@
|
|||||||
</scroller>
|
</scroller>
|
||||||
</scrollView>
|
</scrollView>
|
||||||
<segmentedControl verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="B9Q-hq-K4N">
|
<segmentedControl verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="B9Q-hq-K4N">
|
||||||
<rect key="frame" x="20" y="18" width="67" height="25"/>
|
<rect key="frame" x="20" y="19" width="71" height="23"/>
|
||||||
<segmentedCell key="cell" borderStyle="border" alignment="left" style="texturedSquare" trackingMode="momentary" id="cj3-R6-g1E">
|
<segmentedCell key="cell" borderStyle="border" alignment="left" style="texturedSquare" trackingMode="momentary" id="cj3-R6-g1E">
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
<segments>
|
<segments>
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</segmentedControl>
|
</segmentedControl>
|
||||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="SNe-cc-CZs">
|
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="SNe-cc-CZs">
|
||||||
<rect key="frame" x="383" y="18" width="117" height="25"/>
|
<rect key="frame" x="463" y="18" width="117" height="25"/>
|
||||||
<buttonCell key="cell" type="roundTextured" title="Browse Plugins…" bezelStyle="texturedRounded" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="sqO-8H-n1y">
|
<buttonCell key="cell" type="roundTextured" title="Browse Plugins…" bezelStyle="texturedRounded" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="sqO-8H-n1y">
|
||||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
@@ -176,9 +176,17 @@
|
|||||||
<action selector="browsePlugins:" target="-2" id="16S-2u-Tmi"/>
|
<action selector="browsePlugins:" target="-2" id="16S-2u-Tmi"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
|
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="XIl-03-JZP">
|
||||||
|
<rect key="frame" x="18" y="371" width="250" height="18"/>
|
||||||
|
<buttonCell key="cell" type="check" title="Force loading of incompatible Plugins" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="yak-fS-jtA">
|
||||||
|
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
</buttonCell>
|
||||||
|
</button>
|
||||||
</subviews>
|
</subviews>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="CqP-oK-S8k" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" constant="20" id="1Rj-zS-7t2"/>
|
<constraint firstItem="CqP-oK-S8k" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" constant="20" id="1Rj-zS-7t2"/>
|
||||||
|
<constraint firstItem="XIl-03-JZP" firstAttribute="top" secondItem="aoG-FD-ds8" secondAttribute="bottom" constant="16" id="2Wk-4D-AHu"/>
|
||||||
<constraint firstItem="vBs-Ga-aq0" firstAttribute="top" secondItem="fCk-fL-jU8" secondAttribute="top" id="2h6-C9-4N5"/>
|
<constraint firstItem="vBs-Ga-aq0" firstAttribute="top" secondItem="fCk-fL-jU8" secondAttribute="top" id="2h6-C9-4N5"/>
|
||||||
<constraint firstItem="B9Q-hq-K4N" firstAttribute="top" secondItem="fCk-fL-jU8" secondAttribute="bottom" constant="8" symbolic="YES" id="3vA-Oh-cFO"/>
|
<constraint firstItem="B9Q-hq-K4N" firstAttribute="top" secondItem="fCk-fL-jU8" secondAttribute="bottom" constant="8" symbolic="YES" id="3vA-Oh-cFO"/>
|
||||||
<constraint firstAttribute="bottom" secondItem="B9Q-hq-K4N" secondAttribute="bottom" constant="20" symbolic="YES" id="7HD-ji-Whc"/>
|
<constraint firstAttribute="bottom" secondItem="B9Q-hq-K4N" secondAttribute="bottom" constant="20" symbolic="YES" id="7HD-ji-Whc"/>
|
||||||
@@ -192,13 +200,15 @@
|
|||||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="CqP-oK-S8k" secondAttribute="trailing" constant="20" symbolic="YES" id="TXL-mf-nxu"/>
|
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="CqP-oK-S8k" secondAttribute="trailing" constant="20" symbolic="YES" id="TXL-mf-nxu"/>
|
||||||
<constraint firstItem="SNe-cc-CZs" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="B9Q-hq-K4N" secondAttribute="trailing" constant="8" symbolic="YES" id="a62-en-kDA"/>
|
<constraint firstItem="SNe-cc-CZs" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="B9Q-hq-K4N" secondAttribute="trailing" constant="8" symbolic="YES" id="a62-en-kDA"/>
|
||||||
<constraint firstItem="fCk-fL-jU8" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="20" id="fzW-4b-L8S"/>
|
<constraint firstItem="fCk-fL-jU8" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="20" id="fzW-4b-L8S"/>
|
||||||
|
<constraint firstItem="XIl-03-JZP" firstAttribute="leading" secondItem="CqP-oK-S8k" secondAttribute="leading" id="oqX-wa-jm0"/>
|
||||||
<constraint firstItem="SNe-cc-CZs" firstAttribute="top" secondItem="vBs-Ga-aq0" secondAttribute="bottom" constant="8" symbolic="YES" id="r4X-iM-iYU"/>
|
<constraint firstItem="SNe-cc-CZs" firstAttribute="top" secondItem="vBs-Ga-aq0" secondAttribute="bottom" constant="8" symbolic="YES" id="r4X-iM-iYU"/>
|
||||||
<constraint firstItem="CqP-oK-S8k" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="20" id="rN1-3Z-BBi"/>
|
<constraint firstItem="CqP-oK-S8k" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="20" id="rN1-3Z-BBi"/>
|
||||||
<constraint firstItem="fCk-fL-jU8" firstAttribute="top" secondItem="aoG-FD-ds8" secondAttribute="bottom" constant="8" id="vl9-MY-WW1"/>
|
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="XIl-03-JZP" secondAttribute="trailing" constant="20" symbolic="YES" id="rkN-ew-RtP"/>
|
||||||
|
<constraint firstItem="fCk-fL-jU8" firstAttribute="top" secondItem="XIl-03-JZP" secondAttribute="bottom" constant="8" symbolic="YES" id="vl9-MY-WW1"/>
|
||||||
<constraint firstItem="vBs-Ga-aq0" firstAttribute="leading" secondItem="fCk-fL-jU8" secondAttribute="trailing" constant="8" id="xNu-Sj-xQO"/>
|
<constraint firstItem="vBs-Ga-aq0" firstAttribute="leading" secondItem="fCk-fL-jU8" secondAttribute="trailing" constant="8" id="xNu-Sj-xQO"/>
|
||||||
<constraint firstItem="aoG-FD-ds8" firstAttribute="top" secondItem="CqP-oK-S8k" secondAttribute="bottom" constant="8" symbolic="YES" id="zSW-h3-BrT"/>
|
<constraint firstItem="aoG-FD-ds8" firstAttribute="top" secondItem="CqP-oK-S8k" secondAttribute="bottom" constant="8" symbolic="YES" id="zSW-h3-BrT"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<point key="canvasLocation" x="-163" y="-18"/>
|
<point key="canvasLocation" x="110" y="-97"/>
|
||||||
</customView>
|
</customView>
|
||||||
</objects>
|
</objects>
|
||||||
<resources>
|
<resources>
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
@class KPKEntry;
|
@class KPKEntry;
|
||||||
@class KPKAttribute;
|
@class KPKAttribute;
|
||||||
@class KPKTree;
|
@class KPKTree;
|
||||||
@class MPPluginVersion;
|
|
||||||
|
|
||||||
FOUNDATION_EXPORT NSString *const MPPluginUnkownVersion;
|
FOUNDATION_EXPORT NSString *const MPPluginUnkownVersion;
|
||||||
|
|
||||||
@@ -36,8 +35,7 @@ FOUNDATION_EXPORT NSString *const MPPluginUnkownVersion;
|
|||||||
|
|
||||||
@property (copy, readonly) NSString *identifier;
|
@property (copy, readonly) NSString *identifier;
|
||||||
@property (copy, readonly) NSString *name;
|
@property (copy, readonly) NSString *name;
|
||||||
@property (nonatomic, copy, readonly, nullable) NSString *humanVersionString;
|
@property (nonatomic, copy, readonly, nullable) NSString *shortVersionString;
|
||||||
@property (nonatomic, copy, readonly, nullable) MPPluginVersion *version;
|
|
||||||
@property (nonatomic, copy, readonly) NSString *versionString;
|
@property (nonatomic, copy, readonly) NSString *versionString;
|
||||||
@property (nonatomic, strong, readonly) NSBundle *bundle;
|
@property (nonatomic, strong, readonly) NSBundle *bundle;
|
||||||
|
|
||||||
@@ -89,21 +87,12 @@ FOUNDATION_EXPORT NSString *const MPPluginUnkownVersion;
|
|||||||
- (NSString *)initialValueForAttributeWithKey:(NSString *)key;
|
- (NSString *)initialValueForAttributeWithKey:(NSString *)key;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@protocol MPExportPluginViewController <NSObject>
|
@protocol MPImportPlugin <NSObject>
|
||||||
@required
|
@required
|
||||||
@property (nonatomic, copy) NSDictionary *exportOptions;
|
@property (readonly, copy) NSArray<NSString *> *supportedUTIs;
|
||||||
|
- (KPKTree *)importTreeWithContentsOfURL:(NSURL *)url;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@protocol MPExportPlugin <NSObject>
|
|
||||||
@required
|
|
||||||
/* Ideally supply a list of Formats supported. This format specifier is used when being called */
|
|
||||||
@property (nonatomic, copy) NSDictionary<NSString *, NSString *>* localizedSuportedFormats;
|
|
||||||
- (NSData *)dataForTree:(KPKTree *)tree withFormat:(NSString *)format options:(NSDictionary *)options;
|
|
||||||
@optional
|
|
||||||
- (NSViewController<MPExportPluginViewController> *)exportViewControllerForTree:(KPKTree *)tree withFormat:(NSString *)format;
|
|
||||||
@end
|
|
||||||
|
|
||||||
|
|
||||||
@interface MPPlugin (Deprecated)
|
@interface MPPlugin (Deprecated)
|
||||||
|
|
||||||
- (instancetype)initWithPluginManager:(id)manager;
|
- (instancetype)initWithPluginManager:(id)manager;
|
||||||
|
|||||||
@@ -25,14 +25,13 @@
|
|||||||
#import "MPPluginHost.h"
|
#import "MPPluginHost.h"
|
||||||
#import "MPSettingsHelper.h"
|
#import "MPSettingsHelper.h"
|
||||||
#import "MPPluginConstants.h"
|
#import "MPPluginConstants.h"
|
||||||
#import "MPPluginVersion.h"
|
#import "MPPluginVersionComparator.h"
|
||||||
|
|
||||||
NSString *const MPPluginUnkownVersion = @"unkown.plugin.version";
|
NSString *const MPPluginUnkownVersion = @"unkown.plugin.version";
|
||||||
|
|
||||||
@implementation MPPlugin
|
@implementation MPPlugin
|
||||||
|
|
||||||
@synthesize bundle = _bundle;
|
@synthesize bundle = _bundle;
|
||||||
@synthesize version = _version;
|
|
||||||
|
|
||||||
- (instancetype)initWithPluginHost:(MPPluginHost *)host {
|
- (instancetype)initWithPluginHost:(MPPluginHost *)host {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
@@ -70,21 +69,13 @@ NSString *const MPPluginUnkownVersion = @"unkown.plugin.version";
|
|||||||
return nil == name ? @"Unkown Plugin" : name;
|
return nil == name ? @"Unkown Plugin" : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)humanVersionString {
|
- (NSString *)shortVersionString {
|
||||||
return self.bundle.infoDictionary[@"CFBundleShortVersionString"];
|
return self.bundle.infoDictionary[@"CFBundleShortVersionString"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (MPPluginVersion *)version {
|
|
||||||
if(!_versionInitialized) {
|
|
||||||
_version = [MPPluginVersion versionWithVersionString:self.humanVersionString];
|
|
||||||
_versionInitialized = YES;
|
|
||||||
}
|
|
||||||
return _version;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *)versionString {
|
- (NSString *)versionString {
|
||||||
if(self.bundle) {
|
if(self.bundle) {
|
||||||
NSString *humanVersion = self.humanVersionString;
|
NSString *humanVersion = self.shortVersionString;
|
||||||
NSString *version = self.bundle.infoDictionary[(NSString *)kCFBundleVersionKey];
|
NSString *version = self.bundle.infoDictionary[(NSString *)kCFBundleVersionKey];
|
||||||
if(humanVersion && version) {
|
if(humanVersion && version) {
|
||||||
return [NSString stringWithFormat:@"%@ (%@)", humanVersion, version];
|
return [NSString stringWithFormat:@"%@ (%@)", humanVersion, version];
|
||||||
|
|||||||
@@ -31,14 +31,14 @@ FOUNDATION_EXPORT NSString *const MPPluginHostPluginBundleIdentifiyerKey;
|
|||||||
|
|
||||||
@class MPPlugin;
|
@class MPPlugin;
|
||||||
@class KPKEntry;
|
@class KPKEntry;
|
||||||
@class MPPluginVersion;
|
@protocol MPImportPlugin;
|
||||||
|
|
||||||
@interface MPPluginHost : NSObject
|
@interface MPPluginHost : NSObject
|
||||||
|
|
||||||
/* List of all plugins known to the plugin manager. Disabled plugins are also present! */
|
/* List of all plugins known to the plugin manager. Disabled plugins are also present! */
|
||||||
@property (readonly, copy) NSArray <MPPlugin __kindof*> *plugins;
|
@property (readonly, copy) NSArray <MPPlugin __kindof*> *plugins;
|
||||||
@property (nonatomic, readonly) BOOL loadUnsecurePlugins;
|
@property (readonly, copy) NSArray <MPPlugin __kindof*> *importPlugins;
|
||||||
@property (readonly, copy) MPPluginVersion *version;
|
@property (nonatomic, readonly, copy) NSString *version;
|
||||||
|
|
||||||
+ (instancetype)sharedHost;
|
+ (instancetype)sharedHost;
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
#import "MPPluginEntryActionContext.h"
|
#import "MPPluginEntryActionContext.h"
|
||||||
#import "MPPluginRepository.h"
|
#import "MPPluginRepository.h"
|
||||||
#import "MPPluginRepositoryItem.h"
|
#import "MPPluginRepositoryItem.h"
|
||||||
#import "MPPluginVersion.h"
|
#import "MPPluginVersionComparator.h"
|
||||||
|
|
||||||
#import "NSApplication+MPAdditions.h"
|
#import "NSApplication+MPAdditions.h"
|
||||||
#import "MPSettingsHelper.h"
|
#import "MPSettingsHelper.h"
|
||||||
@@ -48,10 +48,6 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun
|
|||||||
@property (strong) NSMutableArray<NSString *> *entryActionPluginIdentifiers;
|
@property (strong) NSMutableArray<NSString *> *entryActionPluginIdentifiers;
|
||||||
@property (strong) NSMutableArray<NSString *> *customAttributePluginIdentifiers;
|
@property (strong) NSMutableArray<NSString *> *customAttributePluginIdentifiers;
|
||||||
|
|
||||||
|
|
||||||
@property (nonatomic) BOOL loadUnsecurePlugins;
|
|
||||||
@property (copy) NSArray<NSString *> *disabledPlugins;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation MPPluginHost
|
@implementation MPPluginHost
|
||||||
@@ -77,28 +73,27 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun
|
|||||||
self = [super init];
|
self = [super init];
|
||||||
if(self) {
|
if(self) {
|
||||||
_mutablePlugins = [[NSMutableArray alloc] init];
|
_mutablePlugins = [[NSMutableArray alloc] init];
|
||||||
_disabledPlugins = [NSUserDefaults.standardUserDefaults arrayForKey:kMPSettingsKeyLoadUnsecurePlugins];
|
|
||||||
_loadUnsecurePlugins = [NSUserDefaults.standardUserDefaults boolForKey:kMPSettingsKeyLoadUnsecurePlugins];
|
|
||||||
_entryActionPluginIdentifiers = [[NSMutableArray alloc] init];
|
_entryActionPluginIdentifiers = [[NSMutableArray alloc] init];
|
||||||
_customAttributePluginIdentifiers = [[NSMutableArray alloc] init];
|
_customAttributePluginIdentifiers = [[NSMutableArray alloc] init];
|
||||||
_version = [[MPPluginVersion alloc] initWithVersionString:NSBundle.mainBundle.infoDictionary[@"CFBundleShortVersionString"]];
|
|
||||||
|
|
||||||
[self bind:NSStringFromSelector(@selector(loadUnsecurePlugins))
|
|
||||||
toObject:NSUserDefaultsController.sharedUserDefaultsController
|
|
||||||
withKeyPath:[MPSettingsHelper defaultControllerPathForKey:kMPSettingsKeyLoadUnsecurePlugins]
|
|
||||||
options:nil];
|
|
||||||
[self bind:NSStringFromSelector(@selector(disabledPlugins))
|
|
||||||
toObject:NSUserDefaultsController.sharedUserDefaultsController
|
|
||||||
withKeyPath:[MPSettingsHelper defaultControllerPathForKey:kMPSettingsKeyDisabledPlugins]
|
|
||||||
options:nil];
|
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *)version {
|
||||||
|
return NSBundle.mainBundle.infoDictionary[@"CFBundleShortVersionString"];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSArray<MPPlugin *> *)plugins {
|
- (NSArray<MPPlugin *> *)plugins {
|
||||||
return [self.mutablePlugins copy];
|
return [self.mutablePlugins copy];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSArray<MPPlugin *> *)importPlugins {
|
||||||
|
NSPredicate *filterPredicate = [NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
|
||||||
|
return ([evaluatedObject conformsToProtocol:@protocol(MPImportPlugin)]);
|
||||||
|
}];
|
||||||
|
return [self.mutablePlugins filteredArrayUsingPredicate:filterPredicate];
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)installPluginAtURL:(NSURL *)url error:(NSError *__autoreleasing *)error {
|
- (BOOL)installPluginAtURL:(NSURL *)url error:(NSError *__autoreleasing *)error {
|
||||||
if(![self _isValidPluginURL:url]) {
|
if(![self _isValidPluginURL:url]) {
|
||||||
if(error) {
|
if(error) {
|
||||||
@@ -120,9 +115,25 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)disablePlugin:(MPPlugin *)plugin {
|
- (void)disablePlugin:(MPPlugin *)plugin {
|
||||||
|
if(plugin.bundle.bundleIdentifier.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSArray<NSString *> *disabledPlugins = [NSUserDefaults.standardUserDefaults arrayForKey:kMPSettingsKeyDisabledPlugins];
|
||||||
|
if(NSNotFound == [disabledPlugins indexOfObject:plugin.bundle.bundleIdentifier]) {
|
||||||
|
disabledPlugins = [disabledPlugins arrayByAddingObject:plugin.bundle.bundleIdentifier];
|
||||||
|
[NSUserDefaults.standardUserDefaults setObject:disabledPlugins forKey:kMPSettingsKeyDisabledPlugins];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)enablePlugin:(MPPlugin *)plugin {
|
- (void)enablePlugin:(MPPlugin *)plugin {
|
||||||
|
if(plugin.bundle.bundleIdentifier.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSArray<NSString *> *disabledPlugins = [NSUserDefaults.standardUserDefaults arrayForKey:kMPSettingsKeyDisabledPlugins];
|
||||||
|
disabledPlugins = [disabledPlugins filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
|
||||||
|
return ![evaluatedObject isEqualToString:plugin.bundle.bundleIdentifier];
|
||||||
|
}]];
|
||||||
|
[NSUserDefaults.standardUserDefaults setValue:disabledPlugins forKey:kMPSettingsKeyDisabledPlugins];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -133,20 +144,34 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Plugin Loading
|
#pragma mark - Plugin Loading
|
||||||
|
|
||||||
- (void)loadPlugins {
|
- (void)loadPlugins {
|
||||||
[MPPluginRepository.defaultRepository fetchRepositoryDataCompletionHandler:^(NSArray<MPPluginRepositoryItem *> * _Nonnull availablePlugins) {
|
if(MPPluginRepository.defaultRepository.isInitialized) {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
[self _loadPlugins];
|
||||||
[self _loadPlugins:availablePlugins];
|
}
|
||||||
});
|
else {
|
||||||
}];
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||||||
|
selector:@selector(_didUpdateAvailablePlugins:)
|
||||||
|
name:MPPluginRepositoryDidUpdateAvailablePluginsNotification
|
||||||
|
object:MPPluginRepository.defaultRepository];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_loadPlugins:(NSArray<MPPluginRepositoryItem *> *)availablePlugins {
|
- (void)_didUpdateAvailablePlugins:(NSNotification *)notification {
|
||||||
|
[NSNotificationCenter.defaultCenter removeObserver:self
|
||||||
|
name:MPPluginRepositoryDidUpdateAvailablePluginsNotification
|
||||||
|
object:MPPluginRepository.defaultRepository];
|
||||||
|
/* load plugins on the main thread! */
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
[self _loadPlugins];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_loadPlugins {
|
||||||
NSURL *appSupportDir = [NSApp applicationSupportDirectoryURL:YES];
|
NSURL *appSupportDir = [NSApp applicationSupportDirectoryURL:YES];
|
||||||
NSError *error;
|
NSError *error;
|
||||||
NSLog(@"Looking for external plugins at %@.", appSupportDir.path);
|
NSLog(@"Looking for external plugins at %@.", appSupportDir.path);
|
||||||
@@ -176,15 +201,20 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun
|
|||||||
NSLog(@"Skipping %@. No valid plugin file.", pluginURL.path);
|
NSLog(@"Skipping %@. No valid plugin file.", pluginURL.path);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSBundle *pluginBundle = [NSBundle bundleWithURL:pluginURL];
|
NSBundle *pluginBundle = [NSBundle bundleWithURL:pluginURL];
|
||||||
if(!pluginBundle) {
|
if(!pluginBundle) {
|
||||||
NSLog(@"Could not access plugin bundle %@", pluginURL.path);
|
NSLog(@"Could not access plugin bundle %@", pluginURL.path);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if([self _isDisabledPluginBundle:pluginBundle]) {
|
||||||
|
[self _addPluginForBundle:pluginBundle error:NSLocalizedString(@"PLUGIN_ERROR_DISABLED_PLUGIN", "Error for a plugin that is disabled.")];
|
||||||
|
}
|
||||||
|
|
||||||
if(![self _isSignedPluginURL:pluginURL]) {
|
if(![self _isSignedPluginURL:pluginURL]) {
|
||||||
if(self.loadUnsecurePlugins) {
|
BOOL loadInsecurePlugins = [NSUserDefaults.standardUserDefaults boolForKey:kMPSettingsKeyLoadUnsecurePlugins];
|
||||||
|
if(loadInsecurePlugins) {
|
||||||
NSLog(@"Loading unsecure Plugin at %@.", pluginURL.path);
|
NSLog(@"Loading unsecure Plugin at %@.", pluginURL.path);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -200,12 +230,13 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
if([self _validateUniqueBundle:pluginBundle]) {
|
if(![self _isUniqueBundle:pluginBundle]) {
|
||||||
NSLog(@"Plugin %@ already loaded!", pluginBundle.bundleIdentifier);
|
NSLog(@"Plugin %@ already loaded!", pluginBundle.bundleIdentifier);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(![self _isCompatiblePluginBundle:pluginBundle avaiablePlugins:availablePlugins ]) {
|
if(![self _isCompatiblePluginBundle:pluginBundle error:&error]) {
|
||||||
|
NSLog(@"Plugin %@ is not compatible with host!", pluginBundle.bundleIdentifier);
|
||||||
[self _addPluginForBundle:pluginBundle error:NSLocalizedString(@"PLUGIN_ERROR_HOST_VERSION_NOT_SUPPORTED", "Plugin is not with this version of MacPass")];
|
[self _addPluginForBundle:pluginBundle error:NSLocalizedString(@"PLUGIN_ERROR_HOST_VERSION_NOT_SUPPORTED", "Plugin is not with this version of MacPass")];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -233,7 +264,7 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun
|
|||||||
else {
|
else {
|
||||||
plugin = [[pluginBundle.principalClass alloc] initWithPluginHost:self];
|
plugin = [[pluginBundle.principalClass alloc] initWithPluginHost:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(plugin) {
|
if(plugin) {
|
||||||
NSLog(@"Loaded plugin instance %@", pluginBundle.principalClass);
|
NSLog(@"Loaded plugin instance %@", pluginBundle.principalClass);
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPPluginHostWillLoadPlugin
|
[[NSNotificationCenter defaultCenter] postNotificationName:MPPluginHostWillLoadPlugin
|
||||||
@@ -259,19 +290,20 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun
|
|||||||
[self _addPlugin:plugin];
|
[self _addPlugin:plugin];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)_validateUniqueBundle:(NSBundle *)bundle {
|
- (BOOL)_isUniqueBundle:(NSBundle *)bundle {
|
||||||
return ![self pluginWithBundleIdentifier:bundle.bundleIdentifier];
|
return (nil == [self pluginWithBundleIdentifier:bundle.bundleIdentifier]);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)_isCompatiblePluginBundle:(NSBundle *)bundle avaiablePlugins:(NSArray<MPPluginRepositoryItem *> *)availablePlugins {
|
- (BOOL)_isCompatiblePluginBundle:(NSBundle *)bundle error:(NSError * __autoreleasing *)error {
|
||||||
MPPluginRepositoryItem *repoItem;
|
MPPluginRepositoryItem *repoItem;
|
||||||
for(MPPluginRepositoryItem *item in availablePlugins) {
|
for(MPPluginRepositoryItem *item in MPPluginRepository.defaultRepository.availablePlugins) {
|
||||||
if([item.bundleIdentifier isEqualToString:bundle.bundleIdentifier]) {
|
if([item.bundleIdentifier isEqualToString:bundle.bundleIdentifier]) {
|
||||||
repoItem = item;
|
repoItem = item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MPPluginVersion *version = [MPPluginVersion versionWithVersionString:bundle.infoDictionary[@"CFBundleShortVersionString"]];
|
BOOL isCompatible = [repoItem isPluginVersionCompatibleWithHost:bundle.infoDictionary[@"CFBundleShortVersionString"]];
|
||||||
return [repoItem isPluginVersionCompatibleWithHost:version];
|
BOOL loadIncompatible = [NSUserDefaults.standardUserDefaults boolForKey:kMPSettingsKeyLoadIncompatiblePlugins];
|
||||||
|
return (loadIncompatible || isCompatible);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)_isValidPluginURL:(NSURL *)url {
|
- (BOOL)_isValidPluginURL:(NSURL *)url {
|
||||||
@@ -325,6 +357,14 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun
|
|||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)_isDisabledPluginBundle:(NSBundle *)bundle {
|
||||||
|
if(bundle.bundleIdentifier.length == 0) {
|
||||||
|
return YES; // disbable by default if nothing is known
|
||||||
|
}
|
||||||
|
NSArray *disabledPlugins = [NSUserDefaults.standardUserDefaults arrayForKey:kMPSettingsKeyDisabledPlugins];
|
||||||
|
return (NSNotFound != [disabledPlugins indexOfObject:bundle.bundleIdentifier]);
|
||||||
|
}
|
||||||
|
|
||||||
- (void)_addPlugin:(MPPlugin *)plugin {
|
- (void)_addPlugin:(MPPlugin *)plugin {
|
||||||
[self.mutablePlugins addObject:plugin];
|
[self.mutablePlugins addObject:plugin];
|
||||||
if([plugin conformsToProtocol:@protocol(MPEntryActionPlugin)]) {
|
if([plugin conformsToProtocol:@protocol(MPEntryActionPlugin)]) {
|
||||||
|
|||||||
@@ -24,13 +24,20 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
|
|
||||||
@import Foundation;
|
@import Foundation;
|
||||||
|
|
||||||
|
FOUNDATION_EXTERN NSString *const MPPluginRepositoryDidUpdateAvailablePluginsNotification;
|
||||||
|
|
||||||
@class MPPluginRepositoryItem;
|
@class MPPluginRepositoryItem;
|
||||||
|
|
||||||
@interface MPPluginRepository : NSObject
|
@interface MPPluginRepository : NSObject
|
||||||
|
|
||||||
@property (class, strong, readonly) MPPluginRepository *defaultRepository;
|
@property (class, strong, readonly) MPPluginRepository *defaultRepository;
|
||||||
|
@property (readonly) BOOL isInitialized;
|
||||||
- (void)fetchRepositoryDataCompletionHandler:(void (^)(NSArray<MPPluginRepositoryItem *> *availablePlugins))completionHandler;
|
/*
|
||||||
|
this property is set asynchronously, to make sure, you receive valid data,
|
||||||
|
register to MPPluginRepositoryDidUpdateAvailablePlugsinNotification and access
|
||||||
|
availablePlugins after you received at least on notification
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy, readonly) NSArray<MPPluginRepositoryItem *> *availablePlugins;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -24,12 +24,20 @@
|
|||||||
#import "MPConstants.h"
|
#import "MPConstants.h"
|
||||||
#import "MPPluginRepositoryItem.h"
|
#import "MPPluginRepositoryItem.h"
|
||||||
|
|
||||||
|
NSString *const MPPluginRepositoryDidUpdateAvailablePluginsNotification = @"com.hicknhack.macpass.MPPluginRepositoryDidInitializeAvailablePluginsNotification";
|
||||||
|
|
||||||
@interface MPPluginRepository ()
|
@interface MPPluginRepository ()
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSArray<MPPluginRepositoryItem *> *availablePlugins;
|
||||||
|
@property NSTimeInterval lastDataFetchTime;
|
||||||
|
@property BOOL isInitialized;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation MPPluginRepository
|
@implementation MPPluginRepository
|
||||||
|
|
||||||
|
@synthesize availablePlugins = _availablePlugins;
|
||||||
|
|
||||||
+ (instancetype)defaultRepository {
|
+ (instancetype)defaultRepository {
|
||||||
static MPPluginRepository *instance;
|
static MPPluginRepository *instance;
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
@@ -39,6 +47,36 @@
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (instancetype)init {
|
||||||
|
self = [super init];
|
||||||
|
if(self) {
|
||||||
|
_isInitialized = NO;
|
||||||
|
[self fetchRepositoryDataCompletionHandler:^(NSArray<MPPluginRepositoryItem *> * _Nonnull availablePlugins) {
|
||||||
|
self.availablePlugins = availablePlugins;
|
||||||
|
self.isInitialized = YES;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray<MPPluginRepositoryItem *> *)availablePlugins {
|
||||||
|
/* update cache on every read if it's older than 5 minutes */
|
||||||
|
if((NSDate.timeIntervalSinceReferenceDate - self.lastDataFetchTime) > 60*5 ) {
|
||||||
|
NSLog(@"%@: updating available plugins cache.", self.className);
|
||||||
|
[self fetchRepositoryDataCompletionHandler:^(NSArray<MPPluginRepositoryItem *> * _Nonnull availablePlugins) {
|
||||||
|
self.availablePlugins = availablePlugins;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
return _availablePlugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setAvailablePlugins:(NSArray<MPPluginRepositoryItem *> *)availablePlugins {
|
||||||
|
@synchronized (self) {
|
||||||
|
_availablePlugins = [availablePlugins copy];
|
||||||
|
self.lastDataFetchTime = NSDate.timeIntervalSinceReferenceDate;
|
||||||
|
[NSNotificationCenter.defaultCenter postNotificationName:MPPluginRepositoryDidUpdateAvailablePluginsNotification object:self];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)fetchRepositoryDataCompletionHandler:(void (^)(NSArray<MPPluginRepositoryItem *> * _Nonnull))completionHandler {
|
- (void)fetchRepositoryDataCompletionHandler:(void (^)(NSArray<MPPluginRepositoryItem *> * _Nonnull))completionHandler {
|
||||||
NSString *urlString = NSBundle.mainBundle.infoDictionary[MPBundlePluginRepositoryURLKey];
|
NSString *urlString = NSBundle.mainBundle.infoDictionary[MPBundlePluginRepositoryURLKey];
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#import "MPPluginHost.h"
|
#import "MPPluginHost.h"
|
||||||
#import "MPPluginRepository.h"
|
#import "MPPluginRepository.h"
|
||||||
#import "MPPluginRepositoryItem.h"
|
#import "MPPluginRepositoryItem.h"
|
||||||
#import "MPPluginVersion.h"
|
#import "MPPluginVersionComparator.h"
|
||||||
|
|
||||||
|
|
||||||
typedef NS_ENUM(NSUInteger, MPPluginTableColumn) {
|
typedef NS_ENUM(NSUInteger, MPPluginTableColumn) {
|
||||||
@@ -60,17 +60,17 @@ typedef NS_ENUM(NSUInteger, MPPluginTableColumn) {
|
|||||||
view.textField.stringValue = item.name;
|
view.textField.stringValue = item.name;
|
||||||
}
|
}
|
||||||
else if(column == MPPluginTableColumnCurrentVersion) {
|
else if(column == MPPluginTableColumnCurrentVersion) {
|
||||||
view.textField.stringValue = item.currentVersion.versionString;
|
view.textField.stringValue = item.currentVersion;
|
||||||
}
|
}
|
||||||
else if(column == MPPluginTableColumnStatus) {
|
else if(column == MPPluginTableColumnStatus) {
|
||||||
MPPlugin *plugin = [MPPluginHost.sharedHost pluginWithBundleIdentifier:item.bundleIdentifier];
|
MPPlugin *plugin = [MPPluginHost.sharedHost pluginWithBundleIdentifier:item.bundleIdentifier];
|
||||||
if(!plugin) {
|
if(!plugin) {
|
||||||
switch([plugin.version compare:item.currentVersion]) {
|
switch([plugin.shortVersionString compare:item.currentVersion]) {
|
||||||
case NSOrderedSame:
|
case NSOrderedSame:
|
||||||
view.textField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"PLUGIN_BROWSER_LATEST_VERSION_INSTALLED", "Status for an up-to-date plugin in the plugin browser")];
|
view.textField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"PLUGIN_BROWSER_LATEST_VERSION_INSTALLED", "Status for an up-to-date plugin in the plugin browser")];
|
||||||
break;
|
break;
|
||||||
case NSOrderedAscending:
|
case NSOrderedAscending:
|
||||||
view.textField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"PLUGIN_BROWSER_NEWER_VERSION_%@_AVAILABLE", "Status for an outdated plugin version in the plugin browser"), item.currentVersion.versionString];
|
view.textField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"PLUGIN_BROWSER_NEWER_VERSION_%@_AVAILABLE", "Status for an outdated plugin version in the plugin browser"), item.currentVersion];
|
||||||
break;
|
break;
|
||||||
case NSOrderedDescending:
|
case NSOrderedDescending:
|
||||||
view.textField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"PLUGIN_BROWSER_UNKNOWN_PLUGIN_VERSION", "Status for an unkonw plugin version in the plugin browser")];
|
view.textField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"PLUGIN_BROWSER_UNKNOWN_PLUGIN_VERSION", "Status for an unkonw plugin version in the plugin browser")];
|
||||||
@@ -89,12 +89,8 @@ typedef NS_ENUM(NSUInteger, MPPluginTableColumn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)_refreshRepository {
|
- (void)_refreshRepository {
|
||||||
[MPPluginRepository.defaultRepository fetchRepositoryDataCompletionHandler:^(NSArray<MPPluginRepositoryItem *> * _Nonnull availablePlugins) {
|
self.repositoryItems = MPPluginRepository.defaultRepository.availablePlugins;
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
[self.itemTable reloadData];
|
||||||
self.repositoryItems = availablePlugins;
|
|
||||||
[self.itemTable reloadData];
|
|
||||||
});
|
|
||||||
}];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -24,12 +24,12 @@
|
|||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@class MPPluginVersion;
|
@class MPPluginVersionComparator;
|
||||||
|
|
||||||
@interface MPPluginRepositoryItem : NSObject
|
@interface MPPluginRepositoryItem : NSObject
|
||||||
|
|
||||||
@property (copy,readonly, nullable) NSString *name;
|
@property (copy,readonly, nullable) NSString *name;
|
||||||
@property (copy,readonly, nullable) MPPluginVersion *currentVersion;
|
@property (copy,readonly, nullable) NSString *currentVersion;
|
||||||
@property (copy,readonly, nullable) NSString *descriptionText;
|
@property (copy,readonly, nullable) NSString *descriptionText;
|
||||||
@property (copy,readonly, nullable) NSURL *sourceURL;
|
@property (copy,readonly, nullable) NSURL *sourceURL;
|
||||||
@property (copy,readonly, nullable) NSURL *downloadURL;
|
@property (copy,readonly, nullable) NSURL *downloadURL;
|
||||||
@@ -39,7 +39,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
|
|
||||||
+ (instancetype)pluginItemFromDictionary:(NSDictionary *)dict;
|
+ (instancetype)pluginItemFromDictionary:(NSDictionary *)dict;
|
||||||
- (instancetype)initWithDictionary:(NSDictionary *)dict;
|
- (instancetype)initWithDictionary:(NSDictionary *)dict;
|
||||||
- (BOOL)isPluginVersionCompatibleWithHost:(MPPluginVersion *)pluginVersion;
|
- (BOOL)isPluginVersionCompatibleWithHost:(NSString *)pluginVersion;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#import "MPPluginRepositoryItem.h"
|
#import "MPPluginRepositoryItem.h"
|
||||||
#import "MPPluginRepositoryItemVersionInfo.h"
|
#import "MPPluginRepositoryItemVersionInfo.h"
|
||||||
#import "MPPluginVersion.h"
|
#import "MPPluginVersionComparator.h"
|
||||||
#import "MPPluginHost.h"
|
#import "MPPluginHost.h"
|
||||||
#import "NSError+Messages.h"
|
#import "NSError+Messages.h"
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ NSString *const MPPluginItemCompatibiltyKey = @"compatibilty";
|
|||||||
@interface MPPluginRepositoryItem ()
|
@interface MPPluginRepositoryItem ()
|
||||||
|
|
||||||
@property (copy) NSString *name;
|
@property (copy) NSString *name;
|
||||||
@property (copy) MPPluginVersion *currentVersion;
|
@property (copy) NSString *currentVersion;
|
||||||
@property (copy) NSString *descriptionText;
|
@property (copy) NSString *descriptionText;
|
||||||
@property (copy) NSURL *sourceURL;
|
@property (copy) NSURL *sourceURL;
|
||||||
@property (copy) NSURL *downloadURL;
|
@property (copy) NSURL *downloadURL;
|
||||||
@@ -63,7 +63,7 @@ NSString *const MPPluginItemCompatibiltyKey = @"compatibilty";
|
|||||||
self.descriptionText = dict[MPPluginItemDescriptionKey];
|
self.descriptionText = dict[MPPluginItemDescriptionKey];
|
||||||
self.downloadURL = [NSURL URLWithString:dict[MPPluginItemDownloadURLKey]];
|
self.downloadURL = [NSURL URLWithString:dict[MPPluginItemDownloadURLKey]];
|
||||||
self.sourceURL = [NSURL URLWithString:dict[MPPluginItemSourceURLKey]];
|
self.sourceURL = [NSURL URLWithString:dict[MPPluginItemSourceURLKey]];
|
||||||
self.currentVersion = [MPPluginVersion versionWithVersionString:dict[MPPluginItemCurrentVersionKey]];
|
self.currentVersion = dict[MPPluginItemCurrentVersionKey];
|
||||||
self.bundleIdentifier = dict[MPPluginItemBundleIdentifierKey];
|
self.bundleIdentifier = dict[MPPluginItemBundleIdentifierKey];
|
||||||
[self _buildVersionInfos:dict[MPPluginItemCompatibiltyKey]];
|
[self _buildVersionInfos:dict[MPPluginItemCompatibiltyKey]];
|
||||||
|
|
||||||
@@ -76,29 +76,29 @@ NSString *const MPPluginItemCompatibiltyKey = @"compatibilty";
|
|||||||
return (self.name.length > 0 && self.downloadURL);
|
return (self.name.length > 0 && self.downloadURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isPluginVersionCompatibleWithHost:(MPPluginVersion *)pluginVersion {
|
- (BOOL)isPluginVersionCompatibleWithHost:(NSString *)pluginVersion {
|
||||||
if(!pluginVersion) {
|
if(!pluginVersion) {
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
MPPluginVersion *hostVersion = MPPluginHost.sharedHost.version;
|
if(!MPPluginHost.sharedHost.version) {
|
||||||
if(!hostVersion) {
|
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSMutableArray<MPPluginRepositoryItemVersionInfo *> *matches = [[NSMutableArray alloc] init];
|
NSMutableArray<MPPluginRepositoryItemVersionInfo *> *matches = [[NSMutableArray alloc] init];
|
||||||
for(MPPluginRepositoryItemVersionInfo *info in self.compatibilty) {
|
for(MPPluginRepositoryItemVersionInfo *info in self.compatibilty) {
|
||||||
if(NSOrderedSame == [info.version compare:pluginVersion]) {
|
if(NSOrderedSame == [MPPluginVersionComparator compareVersion:info.version toVersion:pluginVersion]) {
|
||||||
[matches addObject:info];
|
[matches addObject:info];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(matches.count != 1) {
|
if(matches.count != 1) {
|
||||||
|
NSLog(@"No unique version match found.");
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
MPPluginRepositoryItemVersionInfo *matchingInfo = matches.firstObject;
|
MPPluginRepositoryItemVersionInfo *matchingInfo = matches.firstObject;
|
||||||
return [matchingInfo isCompatibleWithHostVersion:hostVersion];
|
return [matchingInfo isCompatibleWithHostVersion:MPPluginHost.sharedHost.version];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_buildVersionInfos:(NSArray<NSDictionary *>*)infos {
|
- (void)_buildVersionInfos:(NSArray<NSDictionary *>*)infos {
|
||||||
|
|||||||
@@ -10,18 +10,16 @@
|
|||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@class MPPluginVersion;
|
|
||||||
|
|
||||||
@interface MPPluginRepositoryItemVersionInfo : NSObject
|
@interface MPPluginRepositoryItemVersionInfo : NSObject
|
||||||
|
|
||||||
@property (copy, readonly) MPPluginVersion *version;
|
@property (copy, readonly) NSString *version;
|
||||||
|
|
||||||
+ (instancetype)versionInfoWithDict:(NSDictionary *)dict;
|
+ (instancetype)versionInfoWithDict:(NSDictionary *)dict;
|
||||||
|
|
||||||
- (instancetype)initWithDict:(NSDictionary *)dict NS_DESIGNATED_INITIALIZER;
|
- (instancetype)initWithDict:(NSDictionary *)dict NS_DESIGNATED_INITIALIZER;
|
||||||
- (instancetype)init NS_UNAVAILABLE;
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
|
||||||
- (BOOL)isCompatibleWithHostVersion:(MPPluginVersion *)hostVersion;
|
- (BOOL)isCompatibleWithHostVersion:(NSString *)hostVersion;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "MPPluginRepositoryItemVersionInfo.h"
|
#import "MPPluginRepositoryItemVersionInfo.h"
|
||||||
#import "MPPluginVersion.h"
|
#import "MPPluginVersionComparator.h"
|
||||||
|
|
||||||
NSString *const MPPluginItemCompatibiltyVersionKey = @"pluginVersion";
|
NSString *const MPPluginItemCompatibiltyVersionKey = @"pluginVersion";
|
||||||
NSString *const MPPluginItemCompatibiltyMinimumHostVersionKey = @"minimumHostVersion";
|
NSString *const MPPluginItemCompatibiltyMinimumHostVersionKey = @"minimumHostVersion";
|
||||||
@@ -15,9 +15,9 @@ NSString *const MPPluginItemCompatibiltyMaxiumumHostVersionKey = @"maximumHostVe
|
|||||||
|
|
||||||
@interface MPPluginRepositoryItemVersionInfo ()
|
@interface MPPluginRepositoryItemVersionInfo ()
|
||||||
|
|
||||||
@property (copy) MPPluginVersion *version;
|
@property (copy) NSString *version;
|
||||||
@property (copy) MPPluginVersion *minimumHostVersion;
|
@property (copy) NSString *minimumHostVersion;
|
||||||
@property (copy) MPPluginVersion *maxiumHostVersion;
|
@property (copy) NSString *maxiumHostVersion;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@@ -30,51 +30,21 @@ NSString *const MPPluginItemCompatibiltyMaxiumumHostVersionKey = @"maximumHostVe
|
|||||||
- (instancetype)initWithDict:(NSDictionary *)dict {
|
- (instancetype)initWithDict:(NSDictionary *)dict {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if(self) {
|
if(self) {
|
||||||
NSString *versionString = dict[MPPluginItemCompatibiltyVersionKey];
|
self.version = dict[MPPluginItemCompatibiltyVersionKey];
|
||||||
if(!versionString) {
|
self.minimumHostVersion = dict[MPPluginItemCompatibiltyMinimumHostVersionKey];
|
||||||
NSLog(@"Version information is missing required %@ key.", MPPluginItemCompatibiltyVersionKey);
|
self.maxiumHostVersion = dict[MPPluginItemCompatibiltyMaxiumumHostVersionKey];
|
||||||
self = nil;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
self.version = [MPPluginVersion versionWithVersionString:versionString];
|
|
||||||
if(!self.version) {
|
|
||||||
NSLog(@"Malformed plugin version information: %@.", versionString);
|
|
||||||
self = nil;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
NSString *minimumHostVersionString = dict[MPPluginItemCompatibiltyMinimumHostVersionKey];
|
|
||||||
if(!minimumHostVersionString) {
|
|
||||||
NSLog(@"Version information is missing required %@ key.", MPPluginItemCompatibiltyMinimumHostVersionKey);
|
|
||||||
self = nil;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
self.minimumHostVersion = [MPPluginVersion versionWithVersionString:minimumHostVersionString];
|
|
||||||
if(!self.minimumHostVersion) {
|
|
||||||
NSLog(@"Malformed minimum host version information: %@.", minimumHostVersionString);
|
|
||||||
self = nil;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
NSString *maxiumHostVersionString = dict[MPPluginItemCompatibiltyMaxiumumHostVersionKey];
|
|
||||||
if(maxiumHostVersionString) {
|
|
||||||
self.maxiumHostVersion = [MPPluginVersion versionWithVersionString:maxiumHostVersionString];
|
|
||||||
if(!self.maxiumHostVersion) {
|
|
||||||
NSLog(@"Malformed maxium host version information: %@.", maxiumHostVersionString);
|
|
||||||
self = nil;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isCompatibleWithHostVersion:(MPPluginVersion *)hostVersion {
|
- (BOOL)isCompatibleWithHostVersion:(NSString *)hostVersion {
|
||||||
if(NSOrderedDescending == [self.minimumHostVersion compare:hostVersion]) {
|
if(NSOrderedDescending == [MPPluginVersionComparator compareVersion:self.minimumHostVersion toVersion:hostVersion]) {
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
if(!self.maxiumHostVersion) {
|
if(!self.maxiumHostVersion) {
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
return (NSOrderedAscending != [self.maxiumHostVersion compare:hostVersion]);
|
return (NSOrderedAscending != [MPPluginVersionComparator compareVersion:self.maxiumHostVersion toVersion:hostVersion]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -42,12 +42,13 @@ typedef NS_ENUM(NSUInteger, MPPluginSegmentType) {
|
|||||||
|
|
||||||
@interface MPPluginSettingsController () <NSTableViewDataSource, NSTableViewDelegate>
|
@interface MPPluginSettingsController () <NSTableViewDataSource, NSTableViewDelegate>
|
||||||
|
|
||||||
@property (weak) IBOutlet NSTableView *pluginTableView;
|
@property (strong) IBOutlet NSTableView *pluginTableView;
|
||||||
@property (weak) IBOutlet NSView *settingsView;
|
@property (strong) IBOutlet NSView *settingsView;
|
||||||
@property (strong) IBOutlet NSView *fallbackSettingsView;
|
@property (strong) IBOutlet NSView *fallbackSettingsView;
|
||||||
@property (weak) IBOutlet NSTextField *fallbackDescriptionTextField;
|
@property (strong) IBOutlet NSTextField *fallbackDescriptionTextField;
|
||||||
@property (weak) IBOutlet NSButton *loadInsecurePlugsinCheckButton;
|
@property (strong) IBOutlet NSButton *loadInsecurePlugsinCheckButton;
|
||||||
@property (weak) IBOutlet NSSegmentedControl *addRemovePluginsControl;
|
@property (strong) IBOutlet NSSegmentedControl *addRemovePluginsControl;
|
||||||
|
@property (strong) IBOutlet NSButton *forceIncompatiblePluginsCheckButton;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@@ -75,9 +76,13 @@ typedef NS_ENUM(NSUInteger, MPPluginSegmentType) {
|
|||||||
[self.addRemovePluginsControl setEnabled:NO forSegment:MPRemovePluginSegment];
|
[self.addRemovePluginsControl setEnabled:NO forSegment:MPRemovePluginSegment];
|
||||||
[self.fallbackSettingsView removeFromSuperview];
|
[self.fallbackSettingsView removeFromSuperview];
|
||||||
[self.loadInsecurePlugsinCheckButton bind:NSValueBinding
|
[self.loadInsecurePlugsinCheckButton bind:NSValueBinding
|
||||||
toObject:[NSUserDefaultsController sharedUserDefaultsController]
|
toObject:NSUserDefaultsController.sharedUserDefaultsController
|
||||||
withKeyPath:[MPSettingsHelper defaultControllerPathForKey:kMPSettingsKeyLoadUnsecurePlugins]
|
withKeyPath:[MPSettingsHelper defaultControllerPathForKey:kMPSettingsKeyLoadUnsecurePlugins]
|
||||||
options:nil];
|
options:nil];
|
||||||
|
[self.forceIncompatiblePluginsCheckButton bind:NSValueBinding
|
||||||
|
toObject:NSUserDefaultsController.sharedUserDefaultsController
|
||||||
|
withKeyPath:[MPSettingsHelper defaultControllerPathForKey:kMPSettingsKeyLoadIncompatiblePlugins]
|
||||||
|
options:nil];
|
||||||
[self.pluginTableView registerForDraggedTypes:@[(NSString *)kUTTypeFileURL]];
|
[self.pluginTableView registerForDraggedTypes:@[(NSString *)kUTTypeFileURL]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
//
|
|
||||||
// MPPluginVersion.h
|
|
||||||
// MacPass
|
|
||||||
//
|
|
||||||
// Created by Michael Starke on 05.10.18.
|
|
||||||
// Copyright © 2018 HicknHack Software GmbH. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
|
||||||
|
|
||||||
FOUNDATION_EXPORT NSString *MPPluginVersionWildcard;
|
|
||||||
|
|
||||||
@interface MPPluginVersion : NSObject <NSCopying>
|
|
||||||
|
|
||||||
@property (nonatomic, copy, readonly) NSString *versionString;
|
|
||||||
@property (nonatomic, copy, readonly) NSString *mayorVersion;
|
|
||||||
@property (nonatomic, copy, readonly) NSString *minorVersion;
|
|
||||||
@property (nonatomic, copy, readonly) NSString *patchVersion;
|
|
||||||
|
|
||||||
+ (instancetype)versionWithVersionString:(NSString *)versionString;
|
|
||||||
|
|
||||||
- (instancetype)initWithVersionString:(NSString *)versionString NS_DESIGNATED_INITIALIZER;
|
|
||||||
- (instancetype)init NS_UNAVAILABLE;
|
|
||||||
|
|
||||||
- (NSComparisonResult)compare:(MPPluginVersion *)version;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
//
|
|
||||||
// MPPluginVersion.m
|
|
||||||
// MacPass
|
|
||||||
//
|
|
||||||
// Created by Michael Starke on 05.10.18.
|
|
||||||
// Copyright © 2018 HicknHack Software GmbH. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import "MPPluginVersion.h"
|
|
||||||
|
|
||||||
NSString *MPPluginVersionWildcard = @"*";
|
|
||||||
|
|
||||||
@interface MPPluginVersion ()
|
|
||||||
|
|
||||||
@property (nonatomic, copy) NSString *versionString;
|
|
||||||
@property (nonatomic, copy) NSString *mayorVersion;
|
|
||||||
@property (nonatomic, copy) NSString *minorVersion;
|
|
||||||
@property (nonatomic, copy) NSString *patchVersion;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation MPPluginVersion
|
|
||||||
|
|
||||||
+ (instancetype)versionWithVersionString:(NSString *)versionString {
|
|
||||||
return [[MPPluginVersion alloc] initWithVersionString:versionString];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (instancetype)initWithVersionString:(NSString *)versionString {
|
|
||||||
self = [super init];
|
|
||||||
if(self) {
|
|
||||||
self.mayorVersion = @"0";
|
|
||||||
self.minorVersion = @"0";
|
|
||||||
self.patchVersion = @"0";
|
|
||||||
|
|
||||||
NSArray<NSString *>* components = [versionString componentsSeparatedByString:@"."];
|
|
||||||
if(components.count >= 1) {
|
|
||||||
|
|
||||||
NSString *mayorVersion = components[0].length > 0 ? components[0] : @"0";
|
|
||||||
if([mayorVersion isEqualToString:MPPluginVersionWildcard]) {
|
|
||||||
self.mayorVersion = MPPluginVersionWildcard;
|
|
||||||
self.minorVersion = MPPluginVersionWildcard;
|
|
||||||
self.patchVersion = MPPluginVersionWildcard;
|
|
||||||
self.versionString = [NSString stringWithFormat:@"%@.%@.%@", self.mayorVersion, self.minorVersion, self.patchVersion];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
NSCharacterSet *invalidSet = NSCharacterSet.decimalDigitCharacterSet.invertedSet;
|
|
||||||
NSRange mayorRange = [mayorVersion rangeOfCharacterFromSet:invalidSet];
|
|
||||||
if(mayorRange.location != NSNotFound) {
|
|
||||||
NSLog(@"Invalid Format for Mayor Version");
|
|
||||||
self = nil;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
self.mayorVersion = mayorVersion;
|
|
||||||
|
|
||||||
if(components.count >= 2) {
|
|
||||||
NSString *minorVersion = components[1].length > 0 ? components[1] : @"0";
|
|
||||||
if([minorVersion isEqualToString:MPPluginVersionWildcard]) {
|
|
||||||
self.minorVersion = MPPluginVersionWildcard;
|
|
||||||
self.patchVersion = MPPluginVersionWildcard;
|
|
||||||
self.versionString = [NSString stringWithFormat:@"%@.%@.%@", self.mayorVersion, self.minorVersion, self.patchVersion];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
NSRange minorRange = [minorVersion rangeOfCharacterFromSet:invalidSet];
|
|
||||||
if(minorRange.location != NSNotFound) {
|
|
||||||
NSLog(@"Invalid Format for Minor Version");
|
|
||||||
self.versionString = [NSString stringWithFormat:@"%@.%@.%@", self.mayorVersion, self.minorVersion, self.patchVersion];
|
|
||||||
self = nil;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
self.minorVersion = minorVersion;
|
|
||||||
|
|
||||||
if(components.count == 3) {
|
|
||||||
NSString *patchVersion = components[2].length > 0 ? components[2] : @"0";
|
|
||||||
if([patchVersion isEqualToString:MPPluginVersionWildcard]) {
|
|
||||||
self.patchVersion = MPPluginVersionWildcard;
|
|
||||||
self.versionString = [NSString stringWithFormat:@"%@.%@.%@", self.mayorVersion, self.minorVersion, self.patchVersion];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
NSRange patchRange = [patchVersion rangeOfCharacterFromSet:invalidSet];
|
|
||||||
if(patchRange.location != NSNotFound) {
|
|
||||||
NSLog(@"Invalid Format for Patch Version");
|
|
||||||
self = nil;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
self.patchVersion = patchVersion;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.versionString = [NSString stringWithFormat:@"%@.%@.%@", self.mayorVersion, self.minorVersion, self.patchVersion];
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id)copyWithZone:(NSZone *)zone {
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSComparisonResult)compare:(MPPluginVersion *)version {
|
|
||||||
if([self.versionString isEqualToString:version.versionString]) {
|
|
||||||
return NSOrderedSame;
|
|
||||||
}
|
|
||||||
|
|
||||||
NSArray<NSString *> *myVersions = @[self.mayorVersion, self.minorVersion, self.patchVersion];
|
|
||||||
NSArray<NSString *> *otherVersions = @[version.mayorVersion, version.minorVersion, version.patchVersion];
|
|
||||||
|
|
||||||
for(NSUInteger index = 0; index < 3; index++) {
|
|
||||||
NSString *myVersion = myVersions[index];
|
|
||||||
NSString *otherVersion = otherVersions[index];
|
|
||||||
|
|
||||||
if([myVersion isEqualToString:MPPluginVersionWildcard] || [otherVersion isEqualToString:MPPluginVersionWildcard]) {
|
|
||||||
return NSOrderedSame;
|
|
||||||
}
|
|
||||||
|
|
||||||
NSComparisonResult compare = [myVersion compare:otherVersion options:NSNumericSearch|NSCaseInsensitiveSearch];
|
|
||||||
if(compare != NSOrderedSame) {
|
|
||||||
return compare;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NSOrderedSame;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
30
MacPass/MPPluginVersionComparator.h
Normal file
30
MacPass/MPPluginVersionComparator.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// MPPluginVersion.h
|
||||||
|
// MacPass
|
||||||
|
//
|
||||||
|
// Created by Michael Starke on 05.10.18.
|
||||||
|
// Copyright © 2018 HicknHack Software GmbH. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
FOUNDATION_EXPORT NSString *MPPluginVersionWildcard;
|
||||||
|
|
||||||
|
@interface MPPluginVersionComparator : NSObject
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSUInteger, MPVersionCharacterType ) {
|
||||||
|
kMPVersionCharacterTypeWildcard,
|
||||||
|
kMPVersionCharacterTypeSeparator,
|
||||||
|
kMPVersionCharacterTypeNumeric,
|
||||||
|
kMPVersionCharacterTypeString
|
||||||
|
};
|
||||||
|
|
||||||
|
+ (MPVersionCharacterType)typeOfCharacter:(NSString *)character;
|
||||||
|
+ (NSArray<NSString *> *)splitVersionString:(NSString *)versionString;
|
||||||
|
+ (NSComparisonResult)compareVersion:(NSString *)versionA toVersion:(NSString *)versionB;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
167
MacPass/MPPluginVersionComparator.m
Normal file
167
MacPass/MPPluginVersionComparator.m
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
//
|
||||||
|
// MPPluginVersion.m
|
||||||
|
// MacPass
|
||||||
|
//
|
||||||
|
// Created by Michael Starke on 05.10.18.
|
||||||
|
// Copyright © 2018 HicknHack Software GmbH. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MPPluginVersionComparator.h"
|
||||||
|
|
||||||
|
@implementation MPPluginVersionComparator
|
||||||
|
|
||||||
|
|
||||||
|
+ (MPVersionCharacterType)typeOfCharacter:(NSString *)character {
|
||||||
|
if([character isEqualToString:@"."]) {
|
||||||
|
return kMPVersionCharacterTypeSeparator;
|
||||||
|
}
|
||||||
|
if([character isEqualToString:@"*"]) {
|
||||||
|
return kMPVersionCharacterTypeWildcard;
|
||||||
|
}
|
||||||
|
else if([NSCharacterSet.decimalDigitCharacterSet characterIsMember:[character characterAtIndex:0]]) {
|
||||||
|
return kMPVersionCharacterTypeNumeric;
|
||||||
|
}
|
||||||
|
else if([NSCharacterSet.whitespaceAndNewlineCharacterSet characterIsMember:[character characterAtIndex:0]]) {
|
||||||
|
return kMPVersionCharacterTypeSeparator;
|
||||||
|
}
|
||||||
|
else if([NSCharacterSet.punctuationCharacterSet characterIsMember:[character characterAtIndex:0]]) {
|
||||||
|
return kMPVersionCharacterTypeSeparator;
|
||||||
|
}
|
||||||
|
return kMPVersionCharacterTypeString;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSComparisonResult)compareVersion:(NSString *)versionA toVersion:(NSString *)versionB {
|
||||||
|
NSArray<NSString *>* partsA = [self splitVersionString:versionA];
|
||||||
|
NSArray<NSString *>* partsB = [self splitVersionString:versionB];
|
||||||
|
|
||||||
|
|
||||||
|
MPVersionCharacterType typeA;
|
||||||
|
MPVersionCharacterType typeB;
|
||||||
|
|
||||||
|
NSUInteger minPartsCount = MIN(partsA.count, partsB.count);
|
||||||
|
for(NSUInteger index = 0; index < minPartsCount; index++) {
|
||||||
|
|
||||||
|
NSString *partA = partsA[index];
|
||||||
|
NSString *partB = partsB[index];
|
||||||
|
|
||||||
|
typeA = [self typeOfCharacter:partA];
|
||||||
|
typeB = [self typeOfCharacter:partB];
|
||||||
|
|
||||||
|
if(typeA == typeB) {
|
||||||
|
if(typeA == kMPVersionCharacterTypeNumeric) {
|
||||||
|
NSInteger valueA = partA.integerValue;
|
||||||
|
NSInteger valueB = partB.integerValue;
|
||||||
|
if(valueA < valueB) {
|
||||||
|
return NSOrderedAscending;
|
||||||
|
}
|
||||||
|
else if (valueA > valueB) {
|
||||||
|
return NSOrderedDescending;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(typeA == kMPVersionCharacterTypeString) {
|
||||||
|
NSComparisonResult stringCompare = [partA compare:partB];
|
||||||
|
if(stringCompare != NSOrderedSame) {
|
||||||
|
return stringCompare;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* no wildcards, direct compare */
|
||||||
|
if(typeA != kMPVersionCharacterTypeWildcard && typeB != kMPVersionCharacterTypeWildcard) {
|
||||||
|
if(typeA != kMPVersionCharacterTypeString && typeB == kMPVersionCharacterTypeString) {
|
||||||
|
return NSOrderedDescending;
|
||||||
|
}
|
||||||
|
else if(typeA == kMPVersionCharacterTypeString && typeB != kMPVersionCharacterTypeString) {
|
||||||
|
return NSOrderedAscending;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(typeA == kMPVersionCharacterTypeNumeric) {
|
||||||
|
return NSOrderedDescending;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return NSOrderedAscending;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* we have at least one wildcards */
|
||||||
|
else {
|
||||||
|
/* one is separator, separator wins*/
|
||||||
|
if(typeA == kMPVersionCharacterTypeSeparator) {
|
||||||
|
return NSOrderedDescending;
|
||||||
|
}
|
||||||
|
else if(typeB == kMPVersionCharacterTypeSeparator) {
|
||||||
|
return NSOrderedAscending;
|
||||||
|
}
|
||||||
|
/* one is number or string, gets matched by wildcard */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(partsA.count != partsB.count) {
|
||||||
|
NSArray *longerParts;
|
||||||
|
NSComparisonResult shorterResult;
|
||||||
|
NSComparisonResult longerResult;
|
||||||
|
MPVersionCharacterType lastShortType;
|
||||||
|
if(partsA.count > partsB.count) {
|
||||||
|
lastShortType = typeB;
|
||||||
|
longerParts = partsA;
|
||||||
|
shorterResult = NSOrderedAscending;
|
||||||
|
longerResult = NSOrderedDescending;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lastShortType = typeA;
|
||||||
|
longerParts = partsB;
|
||||||
|
shorterResult = NSOrderedDescending;
|
||||||
|
longerResult = NSOrderedAscending;
|
||||||
|
|
||||||
|
}
|
||||||
|
/* check if wildcard was last part, then the rest does not matter */
|
||||||
|
if(lastShortType == kMPVersionCharacterTypeWildcard) {
|
||||||
|
return NSOrderedSame;
|
||||||
|
}
|
||||||
|
for(NSUInteger longerPartsIndex = minPartsCount; longerPartsIndex < longerParts.count; longerPartsIndex++) {
|
||||||
|
NSString *part = longerParts[longerPartsIndex];
|
||||||
|
MPVersionCharacterType type = [self typeOfCharacter:part];
|
||||||
|
/* overhangpart is string, the shorter wins */
|
||||||
|
if(type == kMPVersionCharacterTypeString) {
|
||||||
|
return shorterResult;
|
||||||
|
}
|
||||||
|
/* overhangpart is number, if not null, longer wins */
|
||||||
|
else if(type == kMPVersionCharacterTypeNumeric) {
|
||||||
|
if(part.integerValue != 0) {
|
||||||
|
return longerResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// versions are considered the same as long as 0, separators or wildcards follow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NSOrderedSame;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+ (NSArray<NSString *> *)splitVersionString:(NSString *)versionString {
|
||||||
|
if(versionString.length == 0) {
|
||||||
|
return @[];
|
||||||
|
}
|
||||||
|
NSMutableArray *versionSegements = [[NSMutableArray alloc] init];
|
||||||
|
NSMutableString *currentSegment = [[versionString substringWithRange:NSMakeRange(0, 1)] mutableCopy];
|
||||||
|
MPVersionCharacterType oldType = [self typeOfCharacter:currentSegment];
|
||||||
|
|
||||||
|
for(NSUInteger characterIndex = 1; characterIndex < versionString.length; characterIndex++) {
|
||||||
|
NSString *character = [versionString substringWithRange:NSMakeRange(characterIndex, 1)];
|
||||||
|
MPVersionCharacterType newType = [self typeOfCharacter:character];
|
||||||
|
if(oldType != newType || newType == kMPVersionCharacterTypeSeparator) {
|
||||||
|
[versionSegements addObject:[currentSegment copy]];
|
||||||
|
[currentSegment setString:character];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
[currentSegment appendString:character];
|
||||||
|
}
|
||||||
|
oldType = newType;
|
||||||
|
}
|
||||||
|
[versionSegements addObject:[currentSegment copy]];
|
||||||
|
return [versionSegements copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -80,6 +80,7 @@ APPKIT_EXTERN NSString *const kMPSettingsKeyUpdatePasswordOnTemplateEntries;
|
|||||||
/* Plugins */
|
/* Plugins */
|
||||||
APPKIT_EXTERN NSString *const kMPSettingsKeyLoadUnsecurePlugins; // If set to YES this will load all plugins regardless of their codesignature status
|
APPKIT_EXTERN NSString *const kMPSettingsKeyLoadUnsecurePlugins; // If set to YES this will load all plugins regardless of their codesignature status
|
||||||
APPKIT_EXTERN NSString *const kMPSettingsKeyDisabledPlugins; // NSArray of bundle identifiers of disabled plugins
|
APPKIT_EXTERN NSString *const kMPSettingsKeyDisabledPlugins; // NSArray of bundle identifiers of disabled plugins
|
||||||
|
APPKIT_EXTERN NSString *const kMPSettingsKeyLoadIncompatiblePlugins; // If set to YES incompatible plugins (no version info, marked as incompatible, etc) will be loaded regardless
|
||||||
|
|
||||||
typedef NS_ENUM(NSUInteger, MPFileChangeStrategy) {
|
typedef NS_ENUM(NSUInteger, MPFileChangeStrategy) {
|
||||||
MPFileChangeStrategyAsk,
|
MPFileChangeStrategyAsk,
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ NSString *const kMPSettingsKeyDoubleClickTitleAction = @"Double
|
|||||||
NSString *const kMPSettingsKeyUpdatePasswordOnTemplateEntries = @"UpdatePasswordOnTemplateEntries";
|
NSString *const kMPSettingsKeyUpdatePasswordOnTemplateEntries = @"UpdatePasswordOnTemplateEntries";
|
||||||
|
|
||||||
NSString *const kMPSettingsKeyLoadUnsecurePlugins = @"LoadUnsecurePlugins";
|
NSString *const kMPSettingsKeyLoadUnsecurePlugins = @"LoadUnsecurePlugins";
|
||||||
|
NSString *const kMPSettingsKeyLoadIncompatiblePlugins = @"LoadIncompatiblePlugins";
|
||||||
NSString *const kMPSettingsKeyDisabledPlugins = @"DisabledPlugins";
|
NSString *const kMPSettingsKeyDisabledPlugins = @"DisabledPlugins";
|
||||||
|
|
||||||
/* Deprecated */
|
/* Deprecated */
|
||||||
@@ -147,7 +148,8 @@ NSString *const kMPDepricatedSettingsKeyLoadUnsecurePlugins = @"MP
|
|||||||
kMPSettingsKeyDoubleClickTitleAction: @(MPDoubleClickTitleActionInspect),
|
kMPSettingsKeyDoubleClickTitleAction: @(MPDoubleClickTitleActionInspect),
|
||||||
kMPSettingsKeyLoadUnsecurePlugins: @NO,
|
kMPSettingsKeyLoadUnsecurePlugins: @NO,
|
||||||
kMPSettingsKeyUpdatePasswordOnTemplateEntries: @YES,
|
kMPSettingsKeyUpdatePasswordOnTemplateEntries: @YES,
|
||||||
kMPSettingsKeyDisabledPlugins: @[]
|
kMPSettingsKeyDisabledPlugins: @[],
|
||||||
|
kMPSettingsKeyLoadIncompatiblePlugins: @NO
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
return standardDefaults;
|
return standardDefaults;
|
||||||
|
|||||||
@@ -161,7 +161,7 @@
|
|||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
</buttonCell>
|
</buttonCell>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="refresh:" target="-2" id="xld-yu-3Q9"/>
|
<action selector="refresh:" target="-2" id="kif-fN-nkM"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Pkh-la-7FU">
|
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Pkh-la-7FU">
|
||||||
|
|||||||
@@ -1,150 +0,0 @@
|
|||||||
//
|
|
||||||
// MPTestPluginVersion.m
|
|
||||||
// MacPassTests
|
|
||||||
//
|
|
||||||
// Created by Michael Starke on 05.10.18.
|
|
||||||
// Copyright © 2018 HicknHack Software GmbH. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import <XCTest/XCTest.h>
|
|
||||||
|
|
||||||
#import "MPPluginVersion.h"
|
|
||||||
|
|
||||||
@interface MPTestPluginVersion : XCTestCase
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation MPTestPluginVersion
|
|
||||||
|
|
||||||
- (void)testVersionExtraction {
|
|
||||||
MPPluginVersion *version = [[MPPluginVersion alloc] initWithVersionString:@"1."];
|
|
||||||
XCTAssertEqualObjects(@"1", version.mayorVersion);
|
|
||||||
XCTAssertEqualObjects(@"0", version.minorVersion);
|
|
||||||
XCTAssertEqualObjects(@"0", version.patchVersion);
|
|
||||||
XCTAssertEqualObjects(@"1.0.0", version.versionString);
|
|
||||||
|
|
||||||
version = [[MPPluginVersion alloc] initWithVersionString:@"0.5"];
|
|
||||||
XCTAssertEqualObjects(@"0", version.mayorVersion);
|
|
||||||
XCTAssertEqualObjects(@"5", version.minorVersion);
|
|
||||||
XCTAssertEqualObjects(@"0", version.patchVersion);
|
|
||||||
XCTAssertEqualObjects(@"0.5.0", version.versionString);
|
|
||||||
|
|
||||||
version = [[MPPluginVersion alloc] initWithVersionString:@".5"];
|
|
||||||
XCTAssertEqualObjects(@"0", version.mayorVersion);
|
|
||||||
XCTAssertEqualObjects(@"5", version.minorVersion);
|
|
||||||
XCTAssertEqualObjects(@"0", version.patchVersion);
|
|
||||||
XCTAssertEqualObjects(@"0.5.0", version.versionString);
|
|
||||||
|
|
||||||
version = [[MPPluginVersion alloc] initWithVersionString:@"5"];
|
|
||||||
XCTAssertEqualObjects(@"5", version.mayorVersion);
|
|
||||||
XCTAssertEqualObjects(@"0", version.minorVersion);
|
|
||||||
XCTAssertEqualObjects(@"0", version.patchVersion);
|
|
||||||
XCTAssertEqualObjects(@"5.0.0", version.versionString);
|
|
||||||
|
|
||||||
version = [[MPPluginVersion alloc] initWithVersionString:@".1."];
|
|
||||||
XCTAssertEqualObjects(@"0", version.mayorVersion);
|
|
||||||
XCTAssertEqualObjects(@"1", version.minorVersion);
|
|
||||||
XCTAssertEqualObjects(@"0", version.patchVersion);
|
|
||||||
XCTAssertEqualObjects(@"0.1.0", version.versionString);
|
|
||||||
|
|
||||||
version = [[MPPluginVersion alloc] initWithVersionString:@".1.1"];
|
|
||||||
XCTAssertEqualObjects(@"0", version.mayorVersion);
|
|
||||||
XCTAssertEqualObjects(@"1", version.minorVersion);
|
|
||||||
XCTAssertEqualObjects(@"1", version.patchVersion);
|
|
||||||
XCTAssertEqualObjects(@"0.1.1", version.versionString);
|
|
||||||
|
|
||||||
version = [[MPPluginVersion alloc] initWithVersionString:@"..1"];
|
|
||||||
XCTAssertEqualObjects(@"0", version.mayorVersion);
|
|
||||||
XCTAssertEqualObjects(@"0", version.minorVersion);
|
|
||||||
XCTAssertEqualObjects(@"1", version.patchVersion);
|
|
||||||
XCTAssertEqualObjects(@"0.0.1", version.versionString);
|
|
||||||
|
|
||||||
version = [[MPPluginVersion alloc] initWithVersionString:@"1.0.0"];
|
|
||||||
XCTAssertEqualObjects(@"1", version.mayorVersion);
|
|
||||||
XCTAssertEqualObjects(@"0", version.minorVersion);
|
|
||||||
XCTAssertEqualObjects(@"0", version.patchVersion);
|
|
||||||
XCTAssertEqualObjects(@"1.0.0", version.versionString);
|
|
||||||
|
|
||||||
version = [[MPPluginVersion alloc] initWithVersionString:@"0.1.0"];
|
|
||||||
XCTAssertEqualObjects(@"0", version.mayorVersion);
|
|
||||||
XCTAssertEqualObjects(@"1", version.minorVersion);
|
|
||||||
XCTAssertEqualObjects(@"0", version.patchVersion);
|
|
||||||
XCTAssertEqualObjects(@"0.1.0", version.versionString);
|
|
||||||
|
|
||||||
version = [[MPPluginVersion alloc] initWithVersionString:@"1.1.1"];
|
|
||||||
XCTAssertEqualObjects(@"1", version.mayorVersion);
|
|
||||||
XCTAssertEqualObjects(@"1", version.minorVersion);
|
|
||||||
XCTAssertEqualObjects(@"1", version.patchVersion);
|
|
||||||
XCTAssertEqualObjects(@"1.1.1", version.versionString);
|
|
||||||
|
|
||||||
version = [[MPPluginVersion alloc] initWithVersionString:@"0.0.5"];
|
|
||||||
XCTAssertEqualObjects(@"0", version.mayorVersion);
|
|
||||||
XCTAssertEqualObjects(@"0", version.minorVersion);
|
|
||||||
XCTAssertEqualObjects(@"5", version.patchVersion);
|
|
||||||
XCTAssertEqualObjects(@"0.0.5", version.versionString);
|
|
||||||
|
|
||||||
version = [[MPPluginVersion alloc] initWithVersionString:@"1.0.3"];
|
|
||||||
XCTAssertEqualObjects(@"1", version.mayorVersion);
|
|
||||||
XCTAssertEqualObjects(@"0", version.minorVersion);
|
|
||||||
XCTAssertEqualObjects(@"3", version.patchVersion);
|
|
||||||
XCTAssertEqualObjects(@"1.0.3", version.versionString);
|
|
||||||
|
|
||||||
version = [[MPPluginVersion alloc] initWithVersionString:@"0.1.4"];
|
|
||||||
XCTAssertEqualObjects(@"0", version.mayorVersion);
|
|
||||||
XCTAssertEqualObjects(@"1", version.minorVersion);
|
|
||||||
XCTAssertEqualObjects(@"4", version.patchVersion);
|
|
||||||
XCTAssertEqualObjects(@"0.1.4", version.versionString);
|
|
||||||
|
|
||||||
version = [[MPPluginVersion alloc] initWithVersionString:@"0.1.*"];
|
|
||||||
XCTAssertEqualObjects(@"0", version.mayorVersion);
|
|
||||||
XCTAssertEqualObjects(@"1", version.minorVersion);
|
|
||||||
XCTAssertEqualObjects(@"*", version.patchVersion);
|
|
||||||
XCTAssertEqualObjects(@"0.1.*", version.versionString);
|
|
||||||
|
|
||||||
version = [[MPPluginVersion alloc] initWithVersionString:@"*.1.0"];
|
|
||||||
XCTAssertEqualObjects(@"*", version.mayorVersion);
|
|
||||||
XCTAssertEqualObjects(@"*", version.minorVersion);
|
|
||||||
XCTAssertEqualObjects(@"*", version.patchVersion);
|
|
||||||
XCTAssertEqualObjects(@"*.*.*", version.versionString);
|
|
||||||
|
|
||||||
version = [[MPPluginVersion alloc] initWithVersionString:@"1.*.0"];
|
|
||||||
XCTAssertEqualObjects(@"1", version.mayorVersion);
|
|
||||||
XCTAssertEqualObjects(@"*", version.minorVersion);
|
|
||||||
XCTAssertEqualObjects(@"*", version.patchVersion);
|
|
||||||
XCTAssertEqualObjects(@"1.*.*", version.versionString);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)testeVersionCompare {
|
|
||||||
|
|
||||||
NSArray *data = @[
|
|
||||||
@[ @"*", @"*", @(NSOrderedSame)],
|
|
||||||
@[ @"1.0.1", @"*", @(NSOrderedSame)],
|
|
||||||
@[ @"*", @"1.0.1", @(NSOrderedSame)],
|
|
||||||
@[ @"1.*", @"1.*", @(NSOrderedSame)],
|
|
||||||
@[ @"1.1.*", @"1.1.*", @(NSOrderedSame)],
|
|
||||||
@[ @"1.1.1", @"1.1.1", @(NSOrderedSame)],
|
|
||||||
@[ @"1.0.1", @"*", @(NSOrderedSame)],
|
|
||||||
@[ @"0.10.*", @"0.10.1", @(NSOrderedSame)],
|
|
||||||
@[ @"10.*.1", @"10.99.*", @(NSOrderedSame)],
|
|
||||||
@[ @"0.9.89", @"0.9.89", @(NSOrderedSame)],
|
|
||||||
@[ @"0.0.1", @"0.0.2", @(NSOrderedAscending)],
|
|
||||||
@[ @"1.10.10", @"1.12.10", @(NSOrderedAscending)],
|
|
||||||
@[ @"20.0.1", @"20.1.0", @(NSOrderedAscending)],
|
|
||||||
@[ @"1.1.1", @"2.*", @(NSOrderedAscending)],
|
|
||||||
@[ @"1.*", @"2.0.*", @(NSOrderedAscending)],
|
|
||||||
@[ @"2.1.1", @"2.0.0", @(NSOrderedDescending)],
|
|
||||||
@[ @"0.1.1", @"0.1.0", @(NSOrderedDescending)],
|
|
||||||
@[ @"1.2.*", @"1.1.*", @(NSOrderedDescending)],
|
|
||||||
@[ @"2.*", @"1.*", @(NSOrderedDescending)]
|
|
||||||
];
|
|
||||||
for(NSUInteger index = 0; index < data.count; index++) {
|
|
||||||
NSArray *set = data[index];
|
|
||||||
MPPluginVersion *versionA = [[MPPluginVersion alloc] initWithVersionString:set[0]];
|
|
||||||
MPPluginVersion *versionB = [[MPPluginVersion alloc] initWithVersionString:set[1]];
|
|
||||||
NSComparisonResult result = [set[2] integerValue];
|
|
||||||
XCTAssertEqual(result, [versionA compare:versionB]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
84
MacPassTests/MPTestPluginVersionComparator.m
Normal file
84
MacPassTests/MPTestPluginVersionComparator.m
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
//
|
||||||
|
// MPTestPluginVersion.m
|
||||||
|
// MacPassTests
|
||||||
|
//
|
||||||
|
// Created by Michael Starke on 05.10.18.
|
||||||
|
// Copyright © 2018 HicknHack Software GmbH. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <XCTest/XCTest.h>
|
||||||
|
|
||||||
|
#import "MPPluginVersionComparator.h"
|
||||||
|
|
||||||
|
@interface MPTestPluginVersion : XCTestCase
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation MPTestPluginVersion
|
||||||
|
|
||||||
|
- (void)testSegmentClasification {
|
||||||
|
XCTAssertEqual([MPPluginVersionComparator typeOfCharacter:@"1"], kMPVersionCharacterTypeNumeric);
|
||||||
|
XCTAssertEqual([MPPluginVersionComparator typeOfCharacter:@"9"], kMPVersionCharacterTypeNumeric);
|
||||||
|
XCTAssertEqual([MPPluginVersionComparator typeOfCharacter:@"*"], kMPVersionCharacterTypeWildcard);
|
||||||
|
XCTAssertEqual([MPPluginVersionComparator typeOfCharacter:@"a"], kMPVersionCharacterTypeString);
|
||||||
|
XCTAssertEqual([MPPluginVersionComparator typeOfCharacter:@"x"], kMPVersionCharacterTypeString);
|
||||||
|
XCTAssertEqual([MPPluginVersionComparator typeOfCharacter:@"Ñ"], kMPVersionCharacterTypeString);
|
||||||
|
XCTAssertEqual([MPPluginVersionComparator typeOfCharacter:@"."], kMPVersionCharacterTypeSeparator);
|
||||||
|
XCTAssertEqual([MPPluginVersionComparator typeOfCharacter:@"-"], kMPVersionCharacterTypeSeparator);
|
||||||
|
XCTAssertEqual([MPPluginVersionComparator typeOfCharacter:@":"], kMPVersionCharacterTypeSeparator);
|
||||||
|
XCTAssertEqual([MPPluginVersionComparator typeOfCharacter:@"!"], kMPVersionCharacterTypeSeparator);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testVersionSplitting {
|
||||||
|
|
||||||
|
NSArray *data = @[
|
||||||
|
@"10.1.99", @[@"10", @".", @"1", @".", @"99"],
|
||||||
|
@"0.152", @[@"0", @".", @"152"],
|
||||||
|
@"1.1.1beta", @[@"1", @".", @"1", @".", @"1", @"beta"],
|
||||||
|
@"beta2.0", @[@"beta", @"2", @".", @"0"],
|
||||||
|
@"*.*.1", @[@"*", @".", @"*", @".", @"1"],
|
||||||
|
@"1-*", @[@"1", @"-", @"*"],
|
||||||
|
@"1-1-1", @[@"1", @"-", @"1", @"-", @"1"]
|
||||||
|
];
|
||||||
|
for(NSUInteger index = 0; index < data.count; index += 2 ) {
|
||||||
|
NSString *versionString = data[index];
|
||||||
|
NSArray *versionParts = data[index+1];
|
||||||
|
XCTAssertEqualObjects([MPPluginVersionComparator splitVersionString:versionString], versionParts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)testVersionCompare {
|
||||||
|
XCTAssertEqual(NSOrderedSame, [MPPluginVersionComparator compareVersion:@"" toVersion:@""]);
|
||||||
|
XCTAssertEqual(NSOrderedSame, [MPPluginVersionComparator compareVersion:@"*" toVersion:@"*"]);
|
||||||
|
XCTAssertEqual(NSOrderedSame, [MPPluginVersionComparator compareVersion:@"1.0.1" toVersion:@"*"]);
|
||||||
|
XCTAssertEqual(NSOrderedSame, [MPPluginVersionComparator compareVersion:@"*" toVersion:@"1.0.1"]);
|
||||||
|
XCTAssertEqual(NSOrderedSame, [MPPluginVersionComparator compareVersion:@"1.*" toVersion:@"1.*"]);
|
||||||
|
XCTAssertEqual(NSOrderedSame, [MPPluginVersionComparator compareVersion:@"1.1.*" toVersion:@"1.1.*"]);
|
||||||
|
XCTAssertEqual(NSOrderedSame, [MPPluginVersionComparator compareVersion:@"1.1.1" toVersion:@"1.1.1"]);
|
||||||
|
XCTAssertEqual(NSOrderedSame, [MPPluginVersionComparator compareVersion:@"1.0.1" toVersion:@"*"]);
|
||||||
|
XCTAssertEqual(NSOrderedSame, [MPPluginVersionComparator compareVersion:@"0.10.*" toVersion:@"0.10.1"]);
|
||||||
|
XCTAssertEqual(NSOrderedSame, [MPPluginVersionComparator compareVersion:@"10.*.1" toVersion:@"10.99.*"]);
|
||||||
|
XCTAssertEqual(NSOrderedSame, [MPPluginVersionComparator compareVersion:@"0.9.89" toVersion:@"0.9.89"]);
|
||||||
|
XCTAssertEqual(NSOrderedSame, [MPPluginVersionComparator compareVersion:@"1.*" toVersion:@"1.*.1"]);
|
||||||
|
XCTAssertEqual(NSOrderedSame, [MPPluginVersionComparator compareVersion:@"1.*.2" toVersion:@"1.*"]);
|
||||||
|
XCTAssertEqual(NSOrderedSame, [MPPluginVersionComparator compareVersion:@"1.0" toVersion:@"1."]);
|
||||||
|
XCTAssertEqual(NSOrderedSame, [MPPluginVersionComparator compareVersion:@"1.0" toVersion:@"1.0.0"]);
|
||||||
|
XCTAssertEqual(NSOrderedSame, [MPPluginVersionComparator compareVersion:@"1.0" toVersion:@"1.0.0.0.0.0.0.0"]);
|
||||||
|
XCTAssertEqual(NSOrderedSame, [MPPluginVersionComparator compareVersion:@"1.0.*" toVersion:@"1.0"]);
|
||||||
|
XCTAssertEqual(NSOrderedAscending, [MPPluginVersionComparator compareVersion:@"0.0.1" toVersion:@"0.0.2"]);
|
||||||
|
XCTAssertEqual(NSOrderedAscending, [MPPluginVersionComparator compareVersion:@"0.0.1b" toVersion:@"0.0.1"]);
|
||||||
|
XCTAssertEqual(NSOrderedAscending, [MPPluginVersionComparator compareVersion:@"1.10.10" toVersion:@"1.12.10"]);
|
||||||
|
XCTAssertEqual(NSOrderedAscending, [MPPluginVersionComparator compareVersion:@"20.0.1" toVersion:@"20.1.0"]);
|
||||||
|
XCTAssertEqual(NSOrderedAscending, [MPPluginVersionComparator compareVersion:@"1.1.1" toVersion:@"2.*"]);
|
||||||
|
XCTAssertEqual(NSOrderedAscending, [MPPluginVersionComparator compareVersion:@"1.*" toVersion:@"2.0.*"]);
|
||||||
|
XCTAssertEqual(NSOrderedDescending, [MPPluginVersionComparator compareVersion:@"2.1.1" toVersion:@"2.0.0"]);
|
||||||
|
XCTAssertEqual(NSOrderedDescending, [MPPluginVersionComparator compareVersion:@"2.0.0" toVersion:@"2.0.0b"]);
|
||||||
|
XCTAssertEqual(NSOrderedDescending, [MPPluginVersionComparator compareVersion:@"2.0.0" toVersion:@"2.0.0.0.0.beta"]);
|
||||||
|
XCTAssertEqual(NSOrderedDescending, [MPPluginVersionComparator compareVersion:@"0.1.1" toVersion:@"0.1.0"]);
|
||||||
|
XCTAssertEqual(NSOrderedDescending, [MPPluginVersionComparator compareVersion:@"1.2.*" toVersion:@"1.1.*"]);
|
||||||
|
XCTAssertEqual(NSOrderedDescending, [MPPluginVersionComparator compareVersion:@"2.*" toVersion:@"1.*"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
Reference in New Issue
Block a user