diff --git a/.swift-version b/.swift-version deleted file mode 100644 index 5186d070..00000000 --- a/.swift-version +++ /dev/null @@ -1 +0,0 @@ -4.0 diff --git a/.swiftlint.yml b/.swiftlint.yml index 4bb6053f..1a360b29 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -29,6 +29,8 @@ opt_in_rules: - implicit_return - implicitly_unwrapped_optional - joined_default_parameter + - last_where + - legacy_multiple - legacy_random - let_var_whitespace - literal_expression_end_indentation @@ -38,13 +40,16 @@ opt_in_rules: - multiline_literal_brackets - multiline_parameters - nimble_operator + - nslocalizedstring_key - operator_usage_whitespace - overridden_super_call - override_in_extension - pattern_matching_keywords - private_action - private_outlet + - prohibited_interface_builder - prohibited_super_call + - reduce_into - redundant_nil_coalescing - single_test_class - sorted_first_last @@ -53,14 +58,18 @@ opt_in_rules: - toggle_bool - unavailable_function - unneeded_parentheses_in_closure_argument + - unowned_variable_capture - untyped_error_in_catch + - unused_declaration - unused_import - - unused_private_declaration - vertical_parameter_alignment_on_call + - vertical_whitespace_closing_braces + - vertical_whitespace_opening_braces + - xct_specific_matcher - yoda_condition + disabled_rules: - cyclomatic_complexity - - identifier_name colon: flexible_right_spacing: true diff --git a/.travis.yml b/.travis.yml index 6f3747f4..43316ab4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,59 +5,49 @@ language: objective-c xcode_workspace: OneTimePassword.xcworkspace xcode_scheme: OneTimePassword (iOS) -osx_image: xcode10 +osx_image: xcode10.3 + +before_install: +- gem install cocoapods -v 1.7 env: - RUNTIME="iOS 10.3" DEVICE="iPhone 7 Plus" - - RUNTIME="iOS 11.3" DEVICE="iPhone X" - - RUNTIME="iOS 12.0" DEVICE="iPhone XS Max" + - RUNTIME="iOS 11.4" DEVICE="iPhone X" + - RUNTIME="iOS 12.4" DEVICE="iPhone XS Max" # Include builds for watchOS matrix: include: - # Include an Xcode 9.0 build to test Swift 4.0 support - - osx_image: xcode9 - env: RUNTIME="iOS 11.0" DEVICE="iPhone 8" - # Include an Xcode 9.2 build to test on iOS 8.x, because Xcode 9.3's iOS 8 simulator fails to launch - - osx_image: xcode9.2 - env: RUNTIME="iOS 8.4" DEVICE="iPhone 4s" - # Include an Xcode 9.4 build to ensure compatibility until Xcode 10 is in widespread use - - osx_image: xcode9.4 - env: RUNTIME="iOS 9.3" DEVICE="iPhone 6s" # Include several build-only jobs for watchOS - xcode_scheme: OneTimePassword (watchOS) - env: BUILD_ONLY="YES" RUNTIME="watchOS 5.0" DEVICE="Apple Watch Series 4 - 44mm" + env: BUILD_ONLY="YES" RUNTIME="watchOS 5.1" DEVICE="Apple Watch Series 4 - 44mm" - xcode_scheme: OneTimePassword (watchOS) - osx_image: xcode9.4 - env: BUILD_ONLY="YES" RUNTIME="watchOS 4.3" DEVICE="Apple Watch Series 3 - 38mm" + env: BUILD_ONLY="YES" RUNTIME="watchOS 4.2" DEVICE="Apple Watch Series 3 - 38mm" - xcode_scheme: OneTimePassword (watchOS) env: BUILD_ONLY="YES" RUNTIME="watchOS 3.2" DEVICE="Apple Watch Series 2 - 42mm" - xcode_scheme: OneTimePassword (watchOS) + osx_image: xcode10.2 env: BUILD_ONLY="YES" RUNTIME="watchOS 2.0" DEVICE="Apple Watch - 38mm" - # Include Carthage builds + # Build with Carthage - env: before_script: script: carthage build --no-skip-current - - osx_image: xcode9 + # Build with CocoaPods + - &cocoapods env: before_script: - script: carthage build --no-skip-current - # Include CocoaPods builds - - env: - before_script: - script: pod lib lint --allow-warnings - - osx_image: xcode9 - env: - before_install: gem update cocoapods - before_script: - script: pod lib lint --allow-warnings --verbose - allow_failures: - # Allow the Xcode 9 `pod lib lint` to fail, as this test method currently has an issue using the custom CommonCrypto module maps. - - osx_image: xcode9 - env: - before_install: gem update cocoapods - before_script: script: pod lib lint --allow-warnings --verbose + # Build with Xcode 10.1 and Swift 4.2 + - &swift42 + osx_image: xcode10.1 + env: RUNTIME="iOS 8.4" DEVICE="iPhone 4s" + script: set -o pipefail && xcodebuild -workspace "$TRAVIS_XCODE_WORKSPACE" -scheme "$TRAVIS_XCODE_SCHEME" -destination "id=$DESTINATION_ID" SWIFT_VERSION=4.2 $ACTIONS | xcpretty -c + - <<: *swift42 + env: RUNTIME="iOS 9.3" DEVICE="iPhone 6s" + # Build with CocoaPods and Swift 4.2 + - <<: *cocoapods + osx_image: xcode10.1 + script: pod lib lint --allow-warnings --verbose --swift-version=4.2 before_script: - DEVICE_ID=com.apple.CoreSimulator.SimDeviceType.$(echo $DEVICE | sed -E -e "s/[ \-]+/ /g" -e "s/[^[:alnum:]]/-/g") diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f71cd62..c5f2c433 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ +## [3.2.0][] (2019-09-20) + +- Upgrade the source to compile with both Swift 4.2 and Swift 5. + ([#201](https://github.com/mattrubin/OneTimePassword/pull/201), + [#202](https://github.com/mattrubin/OneTimePassword/pull/202), + [#204](https://github.com/mattrubin/OneTimePassword/pull/204), + [#209](https://github.com/mattrubin/OneTimePassword/pull/209), + [#215](https://github.com/mattrubin/OneTimePassword/pull/215), + [#216](https://github.com/mattrubin/OneTimePassword/pull/216)) +- Update the SwiftLint configuration, and move the SwiftLint build phase to a separate dedicated target so that new lint errors do not interfere with consumers of the framework. + ([#212](https://github.com/mattrubin/OneTimePassword/pull/212), + [#206](https://github.com/mattrubin/OneTimePassword/pull/206)) +- Upgrade xcconfigs to enable new warnings introduced in Xcode 10.2 + ([#203](https://github.com/mattrubin/OneTimePassword/pull/203)) + ## [3.1.5][] (2019-04-11) - Enable additional linting and CI testing. ([#196](https://github.com/mattrubin/OneTimePassword/pull/196), @@ -175,6 +190,7 @@ Changes between prerelease versions of OneTimePassword version 2 can be found be [develop]: https://github.com/mattrubin/OneTimePassword/compare/3.1.5...develop +[3.2.0]: https://github.com/mattrubin/OneTimePassword/compare/3.1.5...3.2.0 [3.1.5]: https://github.com/mattrubin/OneTimePassword/compare/3.1.4...3.1.5 [3.1.4]: https://github.com/mattrubin/OneTimePassword/compare/3.1.3...3.1.4 [3.1.3]: https://github.com/mattrubin/OneTimePassword/compare/3.1.2...3.1.3 diff --git a/Cartfile.private b/Cartfile.private index 02927c44..7f0ccab3 100644 --- a/Cartfile.private +++ b/Cartfile.private @@ -1,3 +1,3 @@ # Configuration for Carthage (https://github.com/Carthage/Carthage) -github "jspahrsummers/xcconfigs" ~> 0.12 +github "jspahrsummers/xcconfigs" ~> 1.0 diff --git a/Cartfile.resolved b/Cartfile.resolved index 823b32ef..d53ba54a 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,2 +1,2 @@ -github "jspahrsummers/xcconfigs" "0.12" +github "jspahrsummers/xcconfigs" "1.0" github "mattrubin/Base32" "1.1.2+xcode10.2" diff --git a/Carthage/Checkouts/xcconfigs b/Carthage/Checkouts/xcconfigs index bb795558..d0f8992a 160000 --- a/Carthage/Checkouts/xcconfigs +++ b/Carthage/Checkouts/xcconfigs @@ -1 +1 @@ -Subproject commit bb795558a76e5daf3688500055bbcfe243bffa8d +Subproject commit d0f8992afad45262cfe3a3cf512e7127fdcf296c diff --git a/CommonCrypto/README.md b/CommonCrypto/README.md deleted file mode 100644 index a68c3e1a..00000000 --- a/CommonCrypto/README.md +++ /dev/null @@ -1,5 +0,0 @@ -Trying to include the system CommonCrypto headers directly in the framework results in an "include of non-modular header inside framework module" error. The solution is to use these custom CommonCrypto `modulemap` files and reference them from the framework target via the `SWIFT_INCLUDE_PATHS` build settings. - -References: -- https://github.com/soffes/Crypto -- https://ind.ie/labs/blog/using-system-headers-in-swift/ diff --git a/CommonCrypto/appletvos/module.modulemap b/CommonCrypto/appletvos/module.modulemap deleted file mode 100644 index 5289f57e..00000000 --- a/CommonCrypto/appletvos/module.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -module CommonCryptoShim [system] { - header "/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/include/CommonCrypto/CommonCrypto.h" - export * -} diff --git a/CommonCrypto/appletvsimulator/module.modulemap b/CommonCrypto/appletvsimulator/module.modulemap deleted file mode 100644 index a0c4f03b..00000000 --- a/CommonCrypto/appletvsimulator/module.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -module CommonCryptoShim [system] { - header "/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs/AppleTVSimulator.sdk/usr/include/CommonCrypto/CommonCrypto.h" - export * -} diff --git a/CommonCrypto/injectXcodePath.sh b/CommonCrypto/injectXcodePath.sh deleted file mode 100755 index 07746369..00000000 --- a/CommonCrypto/injectXcodePath.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/sh - -# Based on a script by Stefan van den Oord: -# https://ind.ie/labs/blog/using-system-headers-in-swift/ -# https://github.com/svdo/swift-netutils/blob/3.0.1/ifaddrs/injectXcodePath.sh -# -# The MIT License (MIT) Copyright (c) 2015 Stefan van den Oord -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -echo "Injecting Xcode path..." - -defaultXcodePath="header \".*/Contents/Developer" -realXcodePath="header \"`xcode-select -p`" - -fatal() { - echo "[fatal] $1" 1>&2 - exit 1 -} - -absPath() { - case "$1" in - /*) - printf "%s\n" "$1" - ;; - *) - printf "%s\n" "$PWD/$1" - ;; - esac; -} - -scriptDir="`dirname $0`" -absScriptDir="`cd $scriptDir; pwd`" - -main() { - echo " ...in ${absScriptDir}..." - for f in `find ${absScriptDir} -name module.modulemap`; do - echo " ...updating file ${f}" - cat ${f} | sed "s,${defaultXcodePath},${realXcodePath},g" > ${f}.new || fatal "Failed to update modulemap ${f}" - mv ${f}.new ${f} || fatal "Failed to replace modulemap ${f}" - done - echo " ...with new path `xcode-select -p`" -} - -main $* diff --git a/CommonCrypto/iphoneos/module.modulemap b/CommonCrypto/iphoneos/module.modulemap deleted file mode 100644 index 0d53e895..00000000 --- a/CommonCrypto/iphoneos/module.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -module CommonCryptoShim [system] { - header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/CommonCrypto/CommonCrypto.h" - export * -} diff --git a/CommonCrypto/iphonesimulator/module.modulemap b/CommonCrypto/iphonesimulator/module.modulemap deleted file mode 100644 index 787e5f16..00000000 --- a/CommonCrypto/iphonesimulator/module.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -module CommonCryptoShim [system] { - header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/CommonCrypto/CommonCrypto.h" - export * -} diff --git a/CommonCrypto/macosx/module.modulemap b/CommonCrypto/macosx/module.modulemap deleted file mode 100644 index 40b7cfc9..00000000 --- a/CommonCrypto/macosx/module.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -module CommonCryptoShim [system] { - header "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/CommonCrypto/CommonCrypto.h" - export * -} diff --git a/CommonCrypto/watchos/module.modulemap b/CommonCrypto/watchos/module.modulemap deleted file mode 100644 index 152f247a..00000000 --- a/CommonCrypto/watchos/module.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -module CommonCryptoShim [system] { - header "/Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs/WatchOS.sdk/usr/include/CommonCrypto/CommonCrypto.h" - export * -} diff --git a/CommonCrypto/watchsimulator/module.modulemap b/CommonCrypto/watchsimulator/module.modulemap deleted file mode 100644 index 2e6e21b1..00000000 --- a/CommonCrypto/watchsimulator/module.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -module CommonCryptoShim [system] { - header "/Applications/Xcode.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs/WatchSimulator.sdk/usr/include/CommonCrypto/CommonCrypto.h" - export * -} diff --git a/Configuration/OneTimePassword.xcconfig b/Configuration/OneTimePassword.xcconfig index d217849a..5c9105c6 100644 --- a/Configuration/OneTimePassword.xcconfig +++ b/Configuration/OneTimePassword.xcconfig @@ -3,11 +3,3 @@ PRODUCT_BUNDLE_IDENTIFIER = me.mattrubin.onetimepassword; INFOPLIST_FILE = Sources/Info.plist; SWIFT_INSTALL_OBJC_HEADER = NO; - -SWIFT_INCLUDE_PATHS[sdk=appletvos*] = $(SRCROOT)/CommonCrypto/appletvos; -SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*] = $(SRCROOT)/CommonCrypto/appletvsimulator; -SWIFT_INCLUDE_PATHS[sdk=iphoneos*] = $(SRCROOT)/CommonCrypto/iphoneos; -SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*] = $(SRCROOT)/CommonCrypto/iphonesimulator; -SWIFT_INCLUDE_PATHS[sdk=macosx*] = $(SRCROOT)/CommonCrypto/macosx; -SWIFT_INCLUDE_PATHS[sdk=watchos*] = $(SRCROOT)/CommonCrypto/watchos; -SWIFT_INCLUDE_PATHS[sdk=watchsimulator*] = $(SRCROOT)/CommonCrypto/watchsimulator; diff --git a/LICENSE.md b/LICENSE.md index 001f8624..7daa2097 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2013-2017 Matt Rubin and the [OneTimePassword authors](AUTHORS.txt) +Copyright (c) 2013-2019 Matt Rubin and the [OneTimePassword authors](AUTHORS.txt) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/OneTimePassword.podspec b/OneTimePassword.podspec index e56e7bcc..91c0edcc 100644 --- a/OneTimePassword.podspec +++ b/OneTimePassword.podspec @@ -1,31 +1,15 @@ Pod::Spec.new do |s| s.name = "OneTimePassword" - s.version = "3.1.5" + s.version = "3.2.0" s.summary = "A small library for generating TOTP and HOTP one-time passwords." s.homepage = "https://github.com/mattrubin/OneTimePassword" s.license = "MIT" s.author = "Matt Rubin" - s.swift_version = "4.0" + s.swift_versions = ["4.2", "5.0"] s.ios.deployment_target = "8.0" s.watchos.deployment_target = "2.0" s.source = { :git => "https://github.com/mattrubin/OneTimePassword.git", :tag => s.version } s.source_files = "Sources/*.{swift}" s.requires_arc = true s.dependency "Base32", "~> 1.1.2" - s.pod_target_xcconfig = { - "SWIFT_INCLUDE_PATHS[sdk=appletvos*]" => "$(SRCROOT)/OneTimePassword/CommonCrypto/appletvos", - "SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]" => "$(SRCROOT)/OneTimePassword/CommonCrypto/appletvsimulator", - "SWIFT_INCLUDE_PATHS[sdk=iphoneos*]" => "$(SRCROOT)/OneTimePassword/CommonCrypto/iphoneos", - "SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]" => "$(SRCROOT)/OneTimePassword/CommonCrypto/iphonesimulator", - "SWIFT_INCLUDE_PATHS[sdk=macosx*]" => "$(SRCROOT)/OneTimePassword/CommonCrypto/macosx", - "SWIFT_INCLUDE_PATHS[sdk=watchos*]" => "$(SRCROOT)/OneTimePassword/CommonCrypto/watchos", - "SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]" => "$(SRCROOT)/OneTimePassword/CommonCrypto/watchsimulator", - } - s.preserve_paths = "CommonCrypto/*" - # The prepare_command "will be executed after the Pod is downloaded." - # The script is *not* run on every build, or even on every `pod install`, so if the selected - # Xcode path changes after the pod is downloaded, you may need to clear the pod from the cache at - # ~/Library/Caches/CocoaPods so the script can update the modulemaps with the new path. - # https://guides.cocoapods.org/syntax/podspec.html#prepare_command - s.prepare_command = "CommonCrypto/injectXcodePath.sh" end diff --git a/OneTimePassword.xcodeproj/project.pbxproj b/OneTimePassword.xcodeproj/project.pbxproj index 8c5da6e6..7ce32c72 100644 --- a/OneTimePassword.xcodeproj/project.pbxproj +++ b/OneTimePassword.xcodeproj/project.pbxproj @@ -7,16 +7,16 @@ objects = { /* Begin PBXAggregateTarget section */ - FDD3B8661DD6E59E00F87980 /* CommonCrypto */ = { + C9425DE4227501F500EF93BD /* Lint OneTimePassword */ = { isa = PBXAggregateTarget; - buildConfigurationList = FDD3B8671DD6E59E00F87980 /* Build configuration list for PBXAggregateTarget "CommonCrypto" */; + buildConfigurationList = C9425DE7227501F500EF93BD /* Build configuration list for PBXAggregateTarget "Lint OneTimePassword" */; buildPhases = ( - FDD3B86A1DD6E5B700F87980 /* Inject Xcode Path */, + C97CDF2E1BEFB20000D64406 /* Run SwiftLint */, ); dependencies = ( ); - name = CommonCrypto; - productName = CommonCrypto; + name = "Lint OneTimePassword"; + productName = "Lint OneTimePassword"; }; /* End PBXAggregateTarget section */ @@ -27,7 +27,6 @@ 5B39F49F1DBD06F500CD2DAB /* Token+URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9DC7EC3196BD5DF00B50C82 /* Token+URL.swift */; }; 5B39F4A01DBD06F900CD2DAB /* PersistentToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = C95F9FB81C03D6BC00CEA286 /* PersistentToken.swift */; }; 5B39F4A11DBD06FC00CD2DAB /* Keychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9003417196F7046009733E8 /* Keychain.swift */; }; - 5B39F4A21DBD070000CD2DAB /* OneTimePassword.h in Headers */ = {isa = PBXBuildFile; fileRef = C9377D40196B93F900D6C67E /* OneTimePassword.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5B39F4A51DBD08A900CD2DAB /* Base32.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C944A55E1A7EDAE200E08B1E /* Base32.framework */; }; C9003418196F7046009733E8 /* Keychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9003417196F7046009733E8 /* Keychain.swift */; }; C9290C301947D104008AE4DE /* TokenSerializationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9290C2F1947D104008AE4DE /* TokenSerializationTests.swift */; }; @@ -46,7 +45,6 @@ C9B77D771C03078B00BAF6BF /* KeychainTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C93A2514196AFE1100F86892 /* KeychainTests.swift */; }; C9DC7EC4196BD5DF00B50C82 /* Token+URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9DC7EC3196BD5DF00B50C82 /* Token+URL.swift */; }; C9DC7EC8196BDF3B00B50C82 /* Generator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9DC7EC7196BDF3B00B50C82 /* Generator.swift */; }; - C9E639091BDDFF6B002D9231 /* OneTimePassword.h in Headers */ = {isa = PBXBuildFile; fileRef = C9377D40196B93F900D6C67E /* OneTimePassword.h */; settings = {ATTRIBUTES = (Public, ); }; }; C9F544AD1C8391630023CCF0 /* Crypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9F544AC1C8391630023CCF0 /* Crypto.swift */; }; FD6C3C0F1E0200F800EC4528 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD6C3C0E1E0200F800EC4528 /* AppDelegate.swift */; }; FD6C3C341E02033600EC4528 /* OneTimePassword.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C97C82381946E51D00FD9F4C /* OneTimePassword.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -68,13 +66,6 @@ remoteGlobalIDString = C97C82371946E51D00FD9F4C; remoteInfo = "OneTimePassword (iOS)"; }; - FD61F4741DD6E73200166DD9 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C97C822F1946E51D00FD9F4C /* Project object */; - proxyType = 1; - remoteGlobalIDString = FDD3B8661DD6E59E00F87980; - remoteInfo = CommonCrypto; - }; FD6C3C201E0200F900EC4528 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = C97C822F1946E51D00FD9F4C /* Project object */; @@ -89,13 +80,6 @@ remoteGlobalIDString = C97C82371946E51D00FD9F4C; remoteInfo = "OneTimePassword (iOS)"; }; - FDA822711DD6E69F005E4127 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C97C822F1946E51D00FD9F4C /* Project object */; - proxyType = 1; - remoteGlobalIDString = FDD3B8661DD6E59E00F87980; - remoteInfo = CommonCrypto; - }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -116,7 +100,6 @@ 5B39F4941DBD06BA00CD2DAB /* OneTimePassword.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OneTimePassword.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C9003417196F7046009733E8 /* Keychain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Keychain.swift; sourceTree = ""; }; C9290C2F1947D104008AE4DE /* TokenSerializationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenSerializationTests.swift; sourceTree = ""; }; - C9377D40196B93F900D6C67E /* OneTimePassword.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OneTimePassword.h; sourceTree = ""; }; C93A2514196AFE1100F86892 /* KeychainTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeychainTests.swift; sourceTree = ""; }; C93A2515196AFE1100F86892 /* OTPTokenSerializationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OTPTokenSerializationTests.m; sourceTree = ""; }; C93A2519196B1BA400F86892 /* Token.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Token.swift; sourceTree = ""; }; @@ -290,7 +273,6 @@ isa = PBXGroup; children = ( C97C823C1946E51D00FD9F4C /* Info.plist */, - C9377D40196B93F900D6C67E /* OneTimePassword.h */, ); name = "Supporting Files"; sourceTree = ""; @@ -403,25 +385,6 @@ }; /* End PBXGroup section */ -/* Begin PBXHeadersBuildPhase section */ - 5B39F4911DBD06BA00CD2DAB /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 5B39F4A21DBD070000CD2DAB /* OneTimePassword.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C97C82351946E51D00FD9F4C /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - C9E639091BDDFF6B002D9231 /* OneTimePassword.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - /* Begin PBXNativeTarget section */ 5B39F4931DBD06BA00CD2DAB /* OneTimePassword (watchOS) */ = { isa = PBXNativeTarget; @@ -429,12 +392,10 @@ buildPhases = ( 5B39F48F1DBD06BA00CD2DAB /* Sources */, 5B39F4901DBD06BA00CD2DAB /* Frameworks */, - 5B39F4911DBD06BA00CD2DAB /* Headers */, ); buildRules = ( ); dependencies = ( - FDA822721DD6E69F005E4127 /* PBXTargetDependency */, ); name = "OneTimePassword (watchOS)"; productName = "OneTimePassword (watchOS)"; @@ -446,14 +407,11 @@ buildConfigurationList = C97C824E1946E51D00FD9F4C /* Build configuration list for PBXNativeTarget "OneTimePassword (iOS)" */; buildPhases = ( C97C82331946E51D00FD9F4C /* Sources */, - C97CDF2E1BEFB20000D64406 /* Lint */, C97C82341946E51D00FD9F4C /* Frameworks */, - C97C82351946E51D00FD9F4C /* Headers */, ); buildRules = ( ); dependencies = ( - FD61F4751DD6E73200166DD9 /* PBXTargetDependency */, ); name = "OneTimePassword (iOS)"; productName = "OneTimePassword (iOS)"; @@ -529,6 +487,9 @@ LastSwiftMigration = 1020; ProvisioningStyle = Manual; }; + C9425DE4227501F500EF93BD = { + CreatedOnToolsVersion = 10.2.1; + }; C97C82371946E51D00FD9F4C = { CreatedOnToolsVersion = 6.0; LastSwiftMigration = 1020; @@ -550,10 +511,6 @@ LastSwiftMigration = 1020; ProvisioningStyle = Automatic; }; - FDD3B8661DD6E59E00F87980 = { - CreatedOnToolsVersion = 8.1; - ProvisioningStyle = Automatic; - }; }; }; buildConfigurationList = C97C82321946E51D00FD9F4C /* Build configuration list for PBXProject "OneTimePassword" */; @@ -569,12 +526,12 @@ projectDirPath = ""; projectRoot = ""; targets = ( - FDD3B8661DD6E59E00F87980 /* CommonCrypto */, C97C82371946E51D00FD9F4C /* OneTimePassword (iOS) */, C97C82421946E51D00FD9F4C /* OneTimePasswordTests */, C9A486B2196F352E00524F51 /* OneTimePasswordLegacyTests */, FD6C3C0B1E0200F800EC4528 /* OneTimePasswordTestApp */, 5B39F4931DBD06BA00CD2DAB /* OneTimePassword (watchOS) */, + C9425DE4227501F500EF93BD /* Lint OneTimePassword */, ); }; /* End PBXProject section */ @@ -591,33 +548,23 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - C97CDF2E1BEFB20000D64406 /* Lint */ = { + C97CDF2E1BEFB20000D64406 /* Run SwiftLint */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputPaths = ( - ); - name = Lint; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"SwiftLint does not exist, download from https://github.com/realm/SwiftLint\"\nfi"; - }; - FDD3B86A1DD6E5B700F87980 /* Inject Xcode Path */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( + inputFileListPaths = ( ); inputPaths = ( ); - name = "Inject Xcode Path"; + name = "Run SwiftLint"; + outputFileListPaths = ( + ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = $SOURCE_ROOT/CommonCrypto/injectXcodePath.sh; + shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint is not installed. (https://github.com/realm/SwiftLint)\"\nfi\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -692,11 +639,6 @@ target = C97C82371946E51D00FD9F4C /* OneTimePassword (iOS) */; targetProxy = C97C82451946E51D00FD9F4C /* PBXContainerItemProxy */; }; - FD61F4751DD6E73200166DD9 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = FDD3B8661DD6E59E00F87980 /* CommonCrypto */; - targetProxy = FD61F4741DD6E73200166DD9 /* PBXContainerItemProxy */; - }; FD6C3C211E0200F900EC4528 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = FD6C3C0B1E0200F800EC4528 /* OneTimePasswordTestApp */; @@ -707,11 +649,6 @@ target = C97C82371946E51D00FD9F4C /* OneTimePassword (iOS) */; targetProxy = FD6C3C351E02033600EC4528 /* PBXContainerItemProxy */; }; - FDA822721DD6E69F005E4127 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = FDD3B8661DD6E59E00F87980 /* CommonCrypto */; - targetProxy = FDA822711DD6E69F005E4127 /* PBXContainerItemProxy */; - }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -729,13 +666,25 @@ }; name = Release; }; + C9425DE5227501F500EF93BD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + C9425DE6227501F500EF93BD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; C97C824C1946E51D00FD9F4C /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = C996EC2C1A74D5830076B105 /* Debug.xcconfig */; buildSettings = { IPHONEOS_DEPLOYMENT_TARGET = 8.0; SWIFT_TREAT_WARNINGS_AS_ERRORS = NO; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; WATCHOS_DEPLOYMENT_TARGET = 2.0; }; name = Debug; @@ -746,7 +695,7 @@ buildSettings = { IPHONEOS_DEPLOYMENT_TARGET = 8.0; SWIFT_TREAT_WARNINGS_AS_ERRORS = NO; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; WATCHOS_DEPLOYMENT_TARGET = 2.0; }; name = Release; @@ -813,20 +762,6 @@ }; name = Release; }; - FDD3B8681DD6E59E00F87980 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - FDD3B8691DD6E59E00F87980 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -839,6 +774,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + C9425DE7227501F500EF93BD /* Build configuration list for PBXAggregateTarget "Lint OneTimePassword" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C9425DE5227501F500EF93BD /* Debug */, + C9425DE6227501F500EF93BD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; C97C82321946E51D00FD9F4C /* Build configuration list for PBXProject "OneTimePassword" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -884,15 +828,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - FDD3B8671DD6E59E00F87980 /* Build configuration list for PBXAggregateTarget "CommonCrypto" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - FDD3B8681DD6E59E00F87980 /* Debug */, - FDD3B8691DD6E59E00F87980 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; /* End XCConfigurationList section */ }; rootObject = C97C822F1946E51D00FD9F4C /* Project object */; diff --git a/OneTimePassword.xcodeproj/xcshareddata/xcschemes/OneTimePassword (iOS).xcscheme b/OneTimePassword.xcodeproj/xcshareddata/xcschemes/OneTimePassword (iOS).xcscheme index 02a72571..8ce43633 100644 --- a/OneTimePassword.xcodeproj/xcshareddata/xcschemes/OneTimePassword (iOS).xcscheme +++ b/OneTimePassword.xcodeproj/xcshareddata/xcschemes/OneTimePassword (iOS).xcscheme @@ -20,6 +20,20 @@ ReferencedContainer = "container:OneTimePassword.xcodeproj"> + + + + + + + + 3.1 +github "mattrubin/OneTimePassword" ~> 3.2 ```` Then run `carthage update OneTimePassword` to install the latest version of the framework. @@ -39,7 +39,7 @@ Be sure to check the Carthage README file for the latest instructions on [adding Add the following line to your [Podfile][]: ````ruby -pod 'OneTimePassword', '~> 3.1' +pod 'OneTimePassword', '~> 3.2' ```` OneTimePassword, like all pods written in Swift, can only be integrated as a framework. Make sure to add the line `use_frameworks!` to your Podfile or target to opt into frameworks instead of static libraries. @@ -52,8 +52,10 @@ Then run `pod install` to install the latest version of the framework. ## Usage -> The [latest version][swift-4] of OneTimePassword compiles with Swift 4.x, and can be linked with Swift 3.2+ projects using the Swift compiler's [compatibility mode](https://swift.org/blog/swift-4-0-released/#new-compatibility-modes). To use OneTimePassword with earlier versions of Swift, check out the [`swift-3`][swift-3] and [`swift-2.3`][swift-2.3] branches. To use OneTimePassword in an Objective-C based project, check out the [`objc` branch][objc] and the [1.x releases][releases]. +> The [latest version][swift-5] of OneTimePassword can be compiled with either Swift 4.2 or Swift 5, and can be linked with Swift 4 or Swift 5 projects using the Swift compiler's [compatibility mode](https://swift.org/blog/swift-4-0-released/#new-compatibility-modes). To use OneTimePassword with earlier versions of Swift, check out the [`swift-4`][swift-4], [`swift-3`][swift-3], and [`swift-2.3`][swift-2.3] branches. To use OneTimePassword in an Objective-C based project, check out the [`objc` branch][objc] and the [1.x releases][releases]. +[swift-5]: https://github.com/mattrubin/OneTimePassword/tree/swift-5 +[swift-4.2]: https://github.com/mattrubin/OneTimePassword/tree/swift-4.2 [swift-4]: https://github.com/mattrubin/OneTimePassword/tree/swift-4 [swift-3]: https://github.com/mattrubin/OneTimePassword/tree/swift-3 [swift-2.3]: https://github.com/mattrubin/OneTimePassword/tree/swift-2.3 diff --git a/Sources/Crypto.swift b/Sources/Crypto.swift index 3a154099..afdfe7e5 100644 --- a/Sources/Crypto.swift +++ b/Sources/Crypto.swift @@ -2,7 +2,7 @@ // Crypto.swift // OneTimePassword // -// Copyright (c) 2016-2017 Matt Rubin and the OneTimePassword authors +// Copyright (c) 2016-2018 Matt Rubin and the OneTimePassword authors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -24,33 +24,29 @@ // import Foundation -#if swift(>=4.1) - #if canImport(CommonCrypto) - import CommonCrypto - #else - import CommonCryptoShim - #endif -#else - import CommonCryptoShim -#endif +import CommonCrypto func HMAC(algorithm: Generator.Algorithm, key: Data, data: Data) -> Data { let (hashFunction, hashLength) = algorithm.hashInfo let macOut = UnsafeMutablePointer.allocate(capacity: hashLength) defer { - #if swift(>=4.1) macOut.deallocate() - #else - macOut.deallocate(capacity: hashLength) - #endif } + #if swift(>=5.0) + key.withUnsafeBytes { keyBytes in + data.withUnsafeBytes { dataBytes in + CCHmac(hashFunction, keyBytes.baseAddress, key.count, dataBytes.baseAddress, data.count, macOut) + } + } + #else key.withUnsafeBytes { keyBytes in data.withUnsafeBytes { dataBytes in CCHmac(hashFunction, keyBytes, key.count, dataBytes, data.count, macOut) } } + #endif return Data(bytes: macOut, count: hashLength) } diff --git a/Sources/Generator.swift b/Sources/Generator.swift index 22be15c4..b0f420d7 100644 --- a/Sources/Generator.swift +++ b/Sources/Generator.swift @@ -2,7 +2,7 @@ // Generator.swift // OneTimePassword // -// Copyright (c) 2014-2017 Matt Rubin and the OneTimePassword authors +// Copyright (c) 2014-2018 Matt Rubin and the OneTimePassword authors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -86,6 +86,16 @@ public struct Generator: Equatable { let counterData = Data(bytes: &bigCounter, count: MemoryLayout.size) let hash = HMAC(algorithm: algorithm, key: secret, data: counterData) + #if swift(>=5.0) + var truncatedHash = hash.withUnsafeBytes { ptr -> UInt32 in + // Use the last 4 bits of the hash as an offset (0 <= offset <= 15) + let offset = ptr[hash.count - 1] & 0x0f + + // Take 4 bytes from the hash, starting at the given byte offset + let truncatedHashPtr = ptr.baseAddress! + Int(offset) + return truncatedHashPtr.bindMemory(to: UInt32.self, capacity: 1).pointee + } + #else var truncatedHash = hash.withUnsafeBytes { (ptr: UnsafePointer) -> UInt32 in // Use the last 4 bits of the hash as an offset (0 <= offset <= 15) let offset = ptr[hash.count - 1] & 0x0f @@ -96,6 +106,7 @@ public struct Generator: Equatable { $0.pointee } } + #endif // Ensure the four bytes taken from the hash match the current endian format truncatedHash = UInt32(bigEndian: truncatedHash) @@ -192,29 +203,6 @@ public struct Generator: Equatable { } } -#if swift(>=4.1) -#else -/// Compares two `Generator`s for equality. -public func == (lhs: Generator, rhs: Generator) -> Bool { - return (lhs.factor == rhs.factor) - && (lhs.algorithm == rhs.algorithm) - && (lhs.secret == rhs.secret) - && (lhs.digits == rhs.digits) -} - -/// Compares two `Factor`s for equality. -public func == (lhs: Generator.Factor, rhs: Generator.Factor) -> Bool { - switch (lhs, rhs) { - case let (.counter(l), .counter(r)): - return l == r - case let (.timer(l), .timer(r)): - return l == r - default: - return false - } -} -#endif - // MARK: - Private private extension Generator { diff --git a/Sources/Info.plist b/Sources/Info.plist index 132656df..71a2b199 100644 --- a/Sources/Info.plist +++ b/Sources/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.1.5 + 3.2.0 CFBundleSignature ???? CFBundleVersion - 3.1.5 + 3.2.0 NSPrincipalClass diff --git a/Sources/Keychain.swift b/Sources/Keychain.swift index b2c9d1a8..b84be88a 100644 --- a/Sources/Keychain.swift +++ b/Sources/Keychain.swift @@ -2,7 +2,7 @@ // Keychain.swift // OneTimePassword // -// Copyright (c) 2014-2017 Matt Rubin and the OneTimePassword authors +// Copyright (c) 2014-2018 Matt Rubin and the OneTimePassword authors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -52,7 +52,7 @@ public final class Keychain { // tokens as possible. // TODO: Restore deserialization error handling, in a way that provides info on the failure reason and allows // the caller to choose whether to fail completely or recover some data. - return Set(allItems.flatMap({ try? PersistentToken(keychainDictionary: $0) })) + return Set(allItems.compactMap({ try? PersistentToken(keychainDictionary: $0) })) } // MARK: Write diff --git a/Sources/OneTimePassword.h b/Sources/OneTimePassword.h deleted file mode 100644 index c65ec5a8..00000000 --- a/Sources/OneTimePassword.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// OneTimePassword.h -// OneTimePassword -// -// Copyright (c) 2014-2017 Matt Rubin and the OneTimePassword authors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// diff --git a/Sources/PersistentToken.swift b/Sources/PersistentToken.swift index 30da61a2..c739aa43 100644 --- a/Sources/PersistentToken.swift +++ b/Sources/PersistentToken.swift @@ -2,7 +2,7 @@ // PersistentToken.swift // OneTimePassword // -// Copyright (c) 2014-2016 Matt Rubin and the OneTimePassword authors +// Copyright (c) 2014-2018 Matt Rubin and the OneTimePassword authors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -40,19 +40,10 @@ public struct PersistentToken: Equatable, Hashable { self.identifier = identifier } - /// A hash value for the persistent token, providing `Hashable` conformance. - public var hashValue: Int { + /// Hashes the persistent token's identifier into the given hasher, providing `Hashable` conformance. + public func hash(into hasher: inout Hasher) { // Since we expect every `PersistentToken`s identifier to be unique, the identifier's hash // value makes a simple and adequate hash value for the struct as a whole. - return identifier.hashValue + hasher.combine(identifier) } } - -#if swift(>=4.1) -#else -/// Compares two `PersistentToken`s for equality. -public func == (lhs: PersistentToken, rhs: PersistentToken) -> Bool { - return (lhs.identifier == rhs.identifier) - && (lhs.token == rhs.token) -} -#endif diff --git a/Sources/Token+URL.swift b/Sources/Token+URL.swift index fbc0aa26..e47904eb 100644 --- a/Sources/Token+URL.swift +++ b/Sources/Token+URL.swift @@ -2,7 +2,7 @@ // Token+URL.swift // OneTimePassword // -// Copyright (c) 2014-2017 Matt Rubin and the OneTimePassword authors +// Copyright (c) 2014-2018 Matt Rubin and the OneTimePassword authors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Token.swift b/Sources/Token.swift index 3a192788..b5ca6a9b 100644 --- a/Sources/Token.swift +++ b/Sources/Token.swift @@ -2,7 +2,7 @@ // Token.swift // OneTimePassword // -// Copyright (c) 2014-2017 Matt Rubin and the OneTimePassword authors +// Copyright (c) 2014-2018 Matt Rubin and the OneTimePassword authors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -69,13 +69,3 @@ public struct Token: Equatable { return Token(name: name, issuer: issuer, generator: generator.successor()) } } - -#if swift(>=4.1) -#else -/// Compares two `Token`s for equality. -public func == (lhs: Token, rhs: Token) -> Bool { - return (lhs.name == rhs.name) - && (lhs.issuer == rhs.issuer) - && (lhs.generator == rhs.generator) -} -#endif diff --git a/Tests/EquatableTests.swift b/Tests/EquatableTests.swift index c822115f..639003e5 100644 --- a/Tests/EquatableTests.swift +++ b/Tests/EquatableTests.swift @@ -2,7 +2,7 @@ // EquatableTests.swift // OneTimePassword // -// Copyright (c) 2014-2017 Matt Rubin and the OneTimePassword authors +// Copyright (c) 2014-2019 Matt Rubin and the OneTimePassword authors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -28,55 +28,55 @@ import OneTimePassword class EquatableTests: XCTestCase { func testFactorEquality() { - let c0 = Generator.Factor.counter(30) - let c1 = Generator.Factor.counter(60) - let t0 = Generator.Factor.timer(period: 30) - let t1 = Generator.Factor.timer(period: 60) + let smallCounter = Generator.Factor.counter(30) + let bigCounter = Generator.Factor.counter(60) + let shortTimer = Generator.Factor.timer(period: 30) + let longTimer = Generator.Factor.timer(period: 60) - XCTAssertEqual(c0, c0) - XCTAssertEqual(c1, c1) - XCTAssertNotEqual(c0, c1) - XCTAssertNotEqual(c1, c0) + XCTAssertEqual(smallCounter, smallCounter) + XCTAssertEqual(bigCounter, bigCounter) + XCTAssertNotEqual(smallCounter, bigCounter) + XCTAssertNotEqual(bigCounter, smallCounter) - XCTAssertEqual(t0, t0) - XCTAssertEqual(t1, t1) - XCTAssertNotEqual(t0, t1) - XCTAssertNotEqual(t1, t0) + XCTAssertEqual(shortTimer, shortTimer) + XCTAssertEqual(longTimer, longTimer) + XCTAssertNotEqual(shortTimer, longTimer) + XCTAssertNotEqual(longTimer, shortTimer) - XCTAssertNotEqual(c0, t0) - XCTAssertNotEqual(c0, t1) - XCTAssertNotEqual(c1, t0) - XCTAssertNotEqual(c1, t1) + XCTAssertNotEqual(smallCounter, shortTimer) + XCTAssertNotEqual(smallCounter, longTimer) + XCTAssertNotEqual(bigCounter, shortTimer) + XCTAssertNotEqual(bigCounter, longTimer) - XCTAssertNotEqual(t0, c0) - XCTAssertNotEqual(t0, c1) - XCTAssertNotEqual(t1, c0) - XCTAssertNotEqual(t1, c1) + XCTAssertNotEqual(shortTimer, smallCounter) + XCTAssertNotEqual(shortTimer, bigCounter) + XCTAssertNotEqual(longTimer, smallCounter) + XCTAssertNotEqual(longTimer, bigCounter) } func testGeneratorEquality() { - let g = Generator(factor: .counter(0), secret: Data(), algorithm: .sha1, digits: 6) + let generator = Generator(factor: .counter(0), secret: Data(), algorithm: .sha1, digits: 6) let badData = "0".data(using: String.Encoding.utf8)! - XCTAssert(g == Generator(factor: .counter(0), secret: Data(), algorithm: .sha1, digits: 6)) - XCTAssert(g != Generator(factor: .counter(1), secret: Data(), algorithm: .sha1, digits: 6)) - XCTAssert(g != Generator(factor: .counter(0), secret: badData, algorithm: .sha1, digits: 6)) - XCTAssert(g != Generator(factor: .counter(0), secret: Data(), algorithm: .sha256, digits: 6)) - XCTAssert(g != Generator(factor: .counter(0), secret: Data(), algorithm: .sha1, digits: 8)) + XCTAssert(generator == Generator(factor: .counter(0), secret: Data(), algorithm: .sha1, digits: 6)) + XCTAssert(generator != Generator(factor: .counter(1), secret: Data(), algorithm: .sha1, digits: 6)) + XCTAssert(generator != Generator(factor: .counter(0), secret: badData, algorithm: .sha1, digits: 6)) + XCTAssert(generator != Generator(factor: .counter(0), secret: Data(), algorithm: .sha256, digits: 6)) + XCTAssert(generator != Generator(factor: .counter(0), secret: Data(), algorithm: .sha1, digits: 8)) } func testTokenEquality() { guard let generator = Generator(factor: .counter(0), secret: Data(), algorithm: .sha1, digits: 6), - let other_generator = Generator(factor: .counter(1), secret: Data(), algorithm: .sha512, digits: 8) else { + let otherGenerator = Generator(factor: .counter(1), secret: Data(), algorithm: .sha512, digits: 8) else { XCTFail("Failed to construct Generator.") return } - let t = Token(name: "Name", issuer: "Issuer", generator: generator) + let token = Token(name: "Name", issuer: "Issuer", generator: generator) - XCTAssertEqual(t, Token(name: "Name", issuer: "Issuer", generator: generator)) - XCTAssertNotEqual(t, Token(name: "", issuer: "Issuer", generator: generator)) - XCTAssertNotEqual(t, Token(name: "Name", issuer: "", generator: generator)) - XCTAssertNotEqual(t, Token(name: "Name", issuer: "Issuer", generator: other_generator)) + XCTAssertEqual(token, Token(name: "Name", issuer: "Issuer", generator: generator)) + XCTAssertNotEqual(token, Token(name: "", issuer: "Issuer", generator: generator)) + XCTAssertNotEqual(token, Token(name: "Name", issuer: "", generator: generator)) + XCTAssertNotEqual(token, Token(name: "Name", issuer: "Issuer", generator: otherGenerator)) } } diff --git a/Tests/GeneratorTests.swift b/Tests/GeneratorTests.swift index d9e60fa0..0c51ee1f 100644 --- a/Tests/GeneratorTests.swift +++ b/Tests/GeneratorTests.swift @@ -2,7 +2,7 @@ // GeneratorTests.swift // OneTimePassword // -// Copyright (c) 2014-2017 Matt Rubin and the OneTimePassword authors +// Copyright (c) 2014-2019 Matt Rubin and the OneTimePassword authors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -47,28 +47,28 @@ class GeneratorTests: XCTestCase { XCTAssertEqual(generator?.digits, digits) // Create another generator - let other_factor = OneTimePassword.Generator.Factor.timer(period: 123) - let other_secret = "09876543210987654321".data(using: String.Encoding.ascii)! - let other_algorithm = Generator.Algorithm.sha512 - let other_digits = 7 + let otherFactor = OneTimePassword.Generator.Factor.timer(period: 123) + let otherSecret = "09876543210987654321".data(using: String.Encoding.ascii)! + let otherAlgorithm = Generator.Algorithm.sha512 + let otherDigits = 7 - let other_generator = Generator( - factor: other_factor, - secret: other_secret, - algorithm: other_algorithm, - digits: other_digits + let otherGenerator = Generator( + factor: otherFactor, + secret: otherSecret, + algorithm: otherAlgorithm, + digits: otherDigits ) - XCTAssertEqual(other_generator?.factor, other_factor) - XCTAssertEqual(other_generator?.secret, other_secret) - XCTAssertEqual(other_generator?.algorithm, other_algorithm) - XCTAssertEqual(other_generator?.digits, other_digits) + XCTAssertEqual(otherGenerator?.factor, otherFactor) + XCTAssertEqual(otherGenerator?.secret, otherSecret) + XCTAssertEqual(otherGenerator?.algorithm, otherAlgorithm) + XCTAssertEqual(otherGenerator?.digits, otherDigits) // Ensure the generators are different - XCTAssertNotEqual(generator?.factor, other_generator?.factor) - XCTAssertNotEqual(generator?.secret, other_generator?.secret) - XCTAssertNotEqual(generator?.algorithm, other_generator?.algorithm) - XCTAssertNotEqual(generator?.digits, other_generator?.digits) + XCTAssertNotEqual(generator?.factor, otherGenerator?.factor) + XCTAssertNotEqual(generator?.secret, otherGenerator?.secret) + XCTAssertNotEqual(generator?.algorithm, otherGenerator?.algorithm) + XCTAssertNotEqual(generator?.digits, otherGenerator?.digits) } func testCounter() { diff --git a/Tests/KeychainTests.swift b/Tests/KeychainTests.swift index e1ede6e2..c5a77a29 100644 --- a/Tests/KeychainTests.swift +++ b/Tests/KeychainTests.swift @@ -2,7 +2,7 @@ // KeychainTests.swift // OneTimePassword // -// Copyright (c) 2013-2017 Matt Rubin and the OneTimePassword authors +// Copyright (c) 2013-2018 Matt Rubin and the OneTimePassword authors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Tests/TokenSerializationTests.swift b/Tests/TokenSerializationTests.swift index 551809e3..4a278149 100644 --- a/Tests/TokenSerializationTests.swift +++ b/Tests/TokenSerializationTests.swift @@ -2,7 +2,7 @@ // TokenSerializationTests.swift // OneTimePassword // -// Copyright (c) 2014-2017 Matt Rubin and the OneTimePassword authors +// Copyright (c) 2014-2018 Matt Rubin and the OneTimePassword authors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Tests/TokenTests.swift b/Tests/TokenTests.swift index a1ba2495..1f0aa279 100644 --- a/Tests/TokenTests.swift +++ b/Tests/TokenTests.swift @@ -2,7 +2,7 @@ // TokenTests.swift // OneTimePassword // -// Copyright (c) 2014-2017 Matt Rubin and the OneTimePassword authors +// Copyright (c) 2014-2019 Matt Rubin and the OneTimePassword authors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -55,9 +55,9 @@ class TokenTests: XCTestCase { XCTAssertEqual(token.generator, generator) // Create another token - let other_name = "Other Test Name" - let other_issuer = "Other Test Issuer" - guard let other_generator = Generator( + let otherName = "Other Test Name" + let otherIssuer = "Other Test Issuer" + guard let otherGenerator = Generator( factor: .timer(period: 123), secret: otherSecretData, algorithm: .sha512, @@ -67,20 +67,20 @@ class TokenTests: XCTestCase { return } - let other_token = Token( - name: other_name, - issuer: other_issuer, - generator: other_generator + let otherToken = Token( + name: otherName, + issuer: otherIssuer, + generator: otherGenerator ) - XCTAssertEqual(other_token.name, other_name) - XCTAssertEqual(other_token.issuer, other_issuer) - XCTAssertEqual(other_token.generator, other_generator) + XCTAssertEqual(otherToken.name, otherName) + XCTAssertEqual(otherToken.issuer, otherIssuer) + XCTAssertEqual(otherToken.generator, otherGenerator) // Ensure the tokens are different - XCTAssertNotEqual(token.name, other_token.name) - XCTAssertNotEqual(token.issuer, other_token.issuer) - XCTAssertNotEqual(token.generator, other_token.generator) + XCTAssertNotEqual(token.name, otherToken.name) + XCTAssertNotEqual(token.issuer, otherToken.issuer) + XCTAssertNotEqual(token.generator, otherToken.generator) } func testDefaults() { @@ -93,15 +93,15 @@ class TokenTests: XCTestCase { XCTFail("Failed to construct Generator.") return } - let n = "Test Name" - let i = "Test Issuer" + let name = "Test Name" + let issuer = "Test Issuer" - let tokenWithDefaultName = Token(issuer: i, generator: generator) + let tokenWithDefaultName = Token(issuer: issuer, generator: generator) XCTAssertEqual(tokenWithDefaultName.name, "") - XCTAssertEqual(tokenWithDefaultName.issuer, i) + XCTAssertEqual(tokenWithDefaultName.issuer, issuer) - let tokenWithDefaultIssuer = Token(name: n, generator: generator) - XCTAssertEqual(tokenWithDefaultIssuer.name, n) + let tokenWithDefaultIssuer = Token(name: name, generator: generator) + XCTAssertEqual(tokenWithDefaultIssuer.name, name) XCTAssertEqual(tokenWithDefaultIssuer.issuer, "") let tokenWithAllDefaults = Token(generator: generator)