Browse Source

Merge pull request #874 from JamieWhite/master

Using URL's returned from the server for sharing
Marino Faggiana 5 years ago
parent
commit
5b4dd9b88e
100 changed files with 1213 additions and 2589 deletions
  1. 24 0
      CHANGELOG.md
  2. 1 1
      Cartfile
  3. 3 4
      Cartfile.resolved
  4. 4 4
      Carthage/Checkouts/CocoaLumberjack/.travis.yml
  5. 15 1
      Carthage/Checkouts/CocoaLumberjack/CHANGELOG.md
  6. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogCapture.h
  7. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogCapture.m
  8. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogger.h
  9. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDAbstractDatabaseLogger.h
  10. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDAssertMacros.h
  11. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDFileLogger.h
  12. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDFileLogger.m
  13. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDLog+LOGV.h
  14. 2 2
      Carthage/Checkouts/CocoaLumberjack/Classes/DDLog.h
  15. 2 2
      Carthage/Checkouts/CocoaLumberjack/Classes/DDLog.m
  16. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDLogMacros.h
  17. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDOSLogger.h
  18. 2 2
      Carthage/Checkouts/CocoaLumberjack/Classes/DDTTYLogger.h
  19. 3 3
      Carthage/Checkouts/CocoaLumberjack/Classes/DDTTYLogger.m
  20. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDContextFilterLogFormatter.h
  21. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDDispatchQueueLogFormatter.h
  22. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDMultiFormatter.h
  23. 2 2
      Carthage/Checkouts/CocoaLumberjack/CocoaLumberjack.podspec
  24. 1 1
      Carthage/Checkouts/CocoaLumberjack/Framework/Lumberjack/CocoaLumberjack-Info.plist
  25. 1 1
      Carthage/Checkouts/CocoaLumberjack/Framework/Lumberjack/CocoaLumberjackSwift-Info.plist
  26. 0 30
      Carthage/Checkouts/KTVHTTPCache/Framework/KTVHTTPCache.h
  27. 0 15
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCCommon/KTVHCCommon.h
  28. 0 27
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataPrivate.h
  29. 0 25
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataSourceProtocol.h
  30. 0 39
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataSourceQueue.h
  31. 0 152
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataSourceQueue.m
  32. 0 24
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPPingResponse.h
  33. 0 98
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPPingResponse.m
  34. 0 23
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPRequest.h
  35. 0 32
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPURL.h
  36. 0 116
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPURL.m
  37. 0 34
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCTools/KTVHCPathTools.h
  38. 0 184
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCTools/KTVHCPathTools.m
  39. 0 27
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCTools/KTVHCURLTools.h
  40. 0 145
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCTools/KTVHCURLTools.m
  41. 0 139
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHTTPCacheImp.h
  42. 0 224
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHTTPCacheImp.m
  43. 0 16
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/AppDelegate.h
  44. 0 17
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/AppDelegate.m
  45. 0 38
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Assets.xcassets/AppIcon.appiconset/Contents.json
  46. 0 27
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Base.lproj/LaunchScreen.storyboard
  47. 0 203
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Base.lproj/Main.storyboard
  48. 0 27
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Cache/CacheItemView.h
  49. 0 89
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Cache/CacheItemView.m
  50. 0 15
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Cache/CacheItemZoneCell.h
  51. 0 26
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Cache/CacheItemZoneCell.m
  52. 0 13
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Cache/CacheViewController.h
  53. 0 87
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Cache/CacheViewController.m
  54. 0 43
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Info.plist
  55. 0 15
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Media/MediaCell.h
  56. 0 24
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Media/MediaCell.m
  57. 0 18
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Media/MediaItem.h
  58. 0 23
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Media/MediaItem.m
  59. 0 15
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Media/MediaViewController.h
  60. 0 44
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Media/MediaViewController.m
  61. 0 14
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/ViewController.h
  62. 0 97
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/ViewController.m
  63. 0 16
      Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/main.m
  64. 4 4
      Carthage/Checkouts/realm-cocoa/.jenkins.yml
  65. 1 1
      Carthage/Checkouts/realm-cocoa/.travis.yml
  66. 68 0
      Carthage/Checkouts/realm-cocoa/CHANGELOG.md
  67. 3 3
      Carthage/Checkouts/realm-cocoa/Jenkinsfile.releasability
  68. 155 31
      Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMObjectServerTests.mm
  69. 0 173
      Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/SwiftObjectServerTests.swift
  70. 41 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/test-ros-server.js
  71. 2 2
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/dependencies.list
  72. 1 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/CMakeLists.txt
  73. 86 40
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/impl/realm_coordinator.cpp
  74. 5 1
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/impl/realm_coordinator.hpp
  75. 3 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/object.hpp
  76. 6 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/object_accessor.hpp
  77. 85 3
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/object_schema.cpp
  78. 2 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/object_schema.hpp
  79. 25 4
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/property.hpp
  80. 15 8
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/results.cpp
  81. 6 3
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/results.hpp
  82. 1 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/schema.cpp
  83. 9 2
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/shared_realm.cpp
  84. 10 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/shared_realm.hpp
  85. 98 3
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/realm.cpp
  86. 9 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/results.cpp
  87. 116 0
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/schema.cpp
  88. 1 1
      Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/transaction_log_parsing.cpp
  89. 4 0
      Carthage/Checkouts/realm-cocoa/Realm/RLMProperty.mm
  90. 1 1
      Carthage/Checkouts/realm-cocoa/Realm/RLMRealm+Sync.mm
  91. 3 0
      Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager.h
  92. 15 0
      Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager.mm
  93. 3 1
      Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSession.mm
  94. 162 0
      Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSubscription.h
  95. 177 13
      Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSubscription.mm
  96. 2 2
      Carthage/Checkouts/realm-cocoa/Realm/Realm-Info.plist
  97. 3 2
      Carthage/Checkouts/realm-cocoa/Realm/Tests/InterprocessTests.m
  98. 13 50
      Carthage/Checkouts/realm-cocoa/build.sh
  99. 4 4
      Carthage/Checkouts/realm-cocoa/dependencies.list
  100. 1 0
      iOSClient/Library/OCCommunicationLib/OCSharedDto.h

+ 24 - 0
CHANGELOG.md

@@ -6,6 +6,30 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
 
 ## [Unreleased]
 
+## [2.23.6] - 2019-05-22
+- See https://github.com/nextcloud/ios/milestone/50
+
+## [2.23.5] - 2019-04-30
+- See https://github.com/nextcloud/ios/milestone/49
+
+## [2.23.4] - 2019-04-28
+- See https://github.com/nextcloud/ios/milestone/48
+
+## [2.23.3] - 2019-04-3
+- See https://github.com/nextcloud/ios/milestone/47
+
+## [2.23.2] - 2019-03-19
+- See https://github.com/nextcloud/ios/milestone/46
+
+## [2.23.1] - 2019-03-1
+- See https://github.com/nextcloud/ios/milestone/46
+
+## [2.23.0] - 2019-02-18
+- See https://github.com/nextcloud/ios/milestone/45
+
+## [2.22.9] - 2019-02-14
+- See https://github.com/nextcloud/ios/milestone/44
+
 ## [2.22.8] - 2019-01-17
 - See https://github.com/nextcloud/ios/milestone/43
 

+ 1 - 1
Cartfile

@@ -7,7 +7,7 @@ github "ealeksandrov/EAIntroView" == 2.12.0
 github "calimarkus/JDStatusBarNotification" == 1.6.0
 github "ChangbaDevs/KTVHTTPCache" == 2.0.0
 github "jdg/MBProgressHUD" == 1.1.0
-github "realm/realm-cocoa" == 3.14.1
+github "realm/realm-cocoa" == 3.15.0
 github "SVGKit/SVGKit" == 2.1.0
 github "WeTransfer/WeScan" == 1.1.0
 github "malcommac/SwiftRichString" == 3.0.0

+ 3 - 4
Cartfile.resolved

@@ -1,6 +1,6 @@
 github "AFNetworking/AFNetworking" "3.2.1"
 github "ChangbaDevs/KTVHTTPCache" "2.0.0"
-github "CocoaLumberjack/CocoaLumberjack" "3.5.2"
+github "CocoaLumberjack/CocoaLumberjack" "3.5.3"
 github "MortimerGoro/MGSwipeTableCell" "1.6.8"
 github "SVGKit/SVGKit" "2.1.0"
 github "WeTransfer/WeScan" "v1.1.0"
@@ -13,9 +13,8 @@ github "jdg/MBProgressHUD" "1.1.0"
 github "kishikawakatsumi/UICKeyChainStore" "v2.1.2"
 github "malcommac/SwiftRichString" "3.0.0"
 github "marinofaggiana/FastScroll" "81967c2309d29bc2c330d422da612160a30bade8"
-github "marmelroy/Zip" "1.1.0"
-github "realm/realm-cocoa" "v3.14.1"
+github "realm/realm-cocoa" "v3.15.0"
 github "sgr-ksmt/PDFGenerator" "2.1"
 github "tilltue/TLPhotoPicker" "1.8.5"
 github "weichsel/ZIPFoundation" "0.9.9"
-github "yannickl/QRCodeReader.swift" "10.0.0"
+github "yannickl/QRCodeReader.swift" "10.1.0"

+ 4 - 4
Carthage/Checkouts/CocoaLumberjack/.travis.yml

@@ -1,6 +1,6 @@
 
 language: objective-c
-osx_image: xcode10
+osx_image: xcode10.2
 
 branches:
     only:
@@ -15,8 +15,8 @@ env:
 before_install:
     - env
     - locale
-    - gem install cocoapods --pre --no-rdoc --no-ri --no-document --quiet
-    - gem install xcpretty --no-rdoc --no-ri --no-document --quiet
+    - gem install cocoapods --prerelease --no-document --quiet
+    - gem install xcpretty --no-document --quiet
     - pod --version
     - xcpretty --version
     - xcodebuild -version
@@ -51,7 +51,7 @@ script:
     - xcodebuild clean build -project Integration/Integration.xcodeproj -scheme 'macOSSwiftIntegration' -configuration Release -sdk macosx | xcpretty -c
     - xcodebuild clean build -project Integration/Integration.xcodeproj -scheme 'iOSFrameworkIntegration' -sdk iphonesimulator PLATFORM_NAME=iphonesimulator -configuration Release | xcpretty -c
     - xcodebuild clean build -project Integration/Integration.xcodeproj -scheme 'tvOSSwiftIntegration' -destination 'platform=tvOS Simulator,name=Apple TV 4K' -configuration Release -sdk appletvsimulator | xcpretty -c
-    - xcodebuild clean build -project Integration/Integration.xcodeproj -scheme 'watchOSSwiftIntegration' -configuration Release -sdk watchsimulator -destination 'platform=iOS Simulator,name=iPhone XS Max,OS=12.0' | xcpretty -c
+    - xcodebuild clean build -project Integration/Integration.xcodeproj -scheme 'watchOSSwiftIntegration' -configuration Release -sdk watchsimulator -destination 'platform=iOS Simulator,name=iPhone XS Max,OS=12.2' | xcpretty -c
 
     - echo "Run the tests"
     - xcodebuild test -skip-testing:'iOS Tests/DDFileLoggerPerformanceTests' -project Tests/Tests.xcodeproj -scheme 'iOS Tests' -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=9.3' GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c

+ 15 - 1
Carthage/Checkouts/CocoaLumberjack/CHANGELOG.md

@@ -1,4 +1,18 @@
-## [3.5.2 - Xcode 10.1 on 15th, 2019](https://github.com/CocoaLumberjack/CocoaLumberjack/releases/tag/3.5.2)
+## [3.5.3 - Xcode 10.2 on Apr 24th, 2019](https://github.com/CocoaLumberjack/CocoaLumberjack/releases/tag/3.5.3)
+
+### Public
+- Additional compatibility with Swift 5 (backwards compatible with Swift 4) (#1043)
+- Fix warning building with Xcode 10.2 (#1059)
+- Set Xcode 10.2 and Swift 5.0 as a default (#1064)
+- Fix format string crash (#1066)
+
+### Internal
+- Fix warning about syntax (#1054) (#1065)
+- Remove banned APIs (#1056) (#1057)
+- Add CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER & fix warnings (#1059)
+- Use LLONG_MAX instead of LONG_LONG_MAX (#1062)
+
+## [3.5.2 - Xcode 10.1 on Mar 15th, 2019](https://github.com/CocoaLumberjack/CocoaLumberjack/releases/tag/3.5.2)
 
 ### Public
 - Fix reusing of log files after rolling (#1042)

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogCapture.h

@@ -13,7 +13,7 @@
 //   to endorse or promote products derived from this software without specific
 //   prior written permission of Deusty, LLC.
 
-#import "DDASLLogger.h"
+#import <CocoaLumberjack/DDASLLogger.h>
 
 @protocol DDLogger;
 

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogCapture.m

@@ -70,7 +70,7 @@ static DDLogLevel _captureLevel = DDLogLevelVerbose;
 #if !TARGET_OS_IPHONE || (defined(TARGET_SIMULATOR) && TARGET_SIMULATOR)
     int processId = [[NSProcessInfo processInfo] processIdentifier];
     char pid[16];
-    sprintf(pid, "%d", processId);
+    snprintf(pid, sizeof(pid), "%d", processId);
     asl_set_query(query, ASL_KEY_PID, pid, ASL_QUERY_OP_EQUAL | ASL_QUERY_OP_NUMERIC);
 #endif
 }

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogger.h

@@ -20,7 +20,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 // Custom key set on messages sent to ASL
 extern const char* const kDDASLKeyDDLog;

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDAbstractDatabaseLogger.h

@@ -18,7 +18,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 /**
  * This class provides an abstract implementation of a database logger.

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDAssertMacros.h

@@ -20,7 +20,7 @@
         if (!(condition)) {                                                           \
             NSString *description = [NSString stringWithFormat:frmt, ## __VA_ARGS__]; \
             DDLogError(@"%@", description);                                           \
-            NSAssert(NO, description);                                                \
+            NSAssert(NO, @"%@", description);                                         \
         }
 #define DDAssertCondition(condition) DDAssert(condition, @"Condition not satisfied: %s", #condition)
 

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDFileLogger.h

@@ -18,7 +18,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 NS_ASSUME_NONNULL_BEGIN
 

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDFileLogger.m

@@ -826,7 +826,7 @@ unsigned long long const kDDDefaultLogFilesDiskQuota   = 20 * 1024 * 1024; // 20
     });
     #endif
 
-    static NSTimeInterval const kDDMaxTimerDelay = LONG_LONG_MAX / NSEC_PER_SEC;
+    static NSTimeInterval const kDDMaxTimerDelay = LLONG_MAX / NSEC_PER_SEC;
     int64_t delay = (int64_t)(MIN([logFileRollingDate timeIntervalSinceNow], kDDMaxTimerDelay) * (NSTimeInterval) NSEC_PER_SEC);
     dispatch_time_t fireTime = dispatch_time(DISPATCH_TIME_NOW, delay);
 

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDLog+LOGV.h

@@ -18,7 +18,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 /**
  * The constant/variable/method responsible for controlling the current log level.

+ 2 - 2
Carthage/Checkouts/CocoaLumberjack/Classes/DDLog.h

@@ -20,10 +20,10 @@
     #define DD_LEGACY_MACROS 1
 #endif
 // DD_LEGACY_MACROS is checked in the file itself
-#import "DDLegacyMacros.h"
+#import <CocoaLumberjack/DDLegacyMacros.h>
 
 // Names of loggers.
-#import "DDLoggerNames.h"
+#import <CocoaLumberjack/DDLoggerNames.h>
 
 #if OS_OBJECT_USE_OBJC
     #define DISPATCH_QUEUE_REFERENCE_TYPE strong

+ 2 - 2
Carthage/Checkouts/CocoaLumberjack/Classes/DDLog.m

@@ -43,7 +43,7 @@
 // We maintain the NS prefix on the macros to be explicit about the fact that we're using NSLog.
 
 #ifndef DD_DEBUG
-    #define DD_DEBUG NO
+    #define DD_DEBUG 0
 #endif
 
 #define NSLogDebug(frmt, ...) do{ if(DD_DEBUG) NSLog((frmt), ##__VA_ARGS__); } while(0)
@@ -619,7 +619,7 @@ static NSUInteger _numProcessors;
 
         NSUInteger bufferSize = numClasses;
 
-        classes = numClasses ? (Class *)malloc(sizeof(Class) * bufferSize) : NULL;
+        classes = numClasses ? (Class *)calloc(bufferSize, sizeof(Class)) : NULL;
         if (classes == NULL) {
             return @[]; //no memory or classes?
         }

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDLogMacros.h

@@ -18,7 +18,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 /**
  * The constant/variable/method responsible for controlling the current log level.

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDOSLogger.h

@@ -20,7 +20,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 /**
  * This class provides a logger for the Apple os_log facility.

+ 2 - 2
Carthage/Checkouts/CocoaLumberjack/Classes/DDTTYLogger.h

@@ -18,7 +18,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 #define LOG_CONTEXT_ALL INT_MAX
 
@@ -31,7 +31,7 @@
     static inline DDColor* DDMakeColor(CGFloat r, CGFloat g, CGFloat b) {return [DDColor colorWithRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f];}
 #elif defined(DD_CLI) || !__has_include(<AppKit/NSColor.h>)
     // OS X CLI
-    #import "CLIColor.h"
+    #import <CocoaLumberjack/CLIColor.h>
     typedef CLIColor DDColor;
     static inline DDColor* DDMakeColor(CGFloat r, CGFloat g, CGFloat b) {return [DDColor colorWithCalibratedRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f];}
 #else

+ 3 - 3
Carthage/Checkouts/CocoaLumberjack/Classes/DDTTYLogger.m

@@ -844,7 +844,7 @@ static DDTTYLogger *sharedInstance;
             _appLen = [_appName lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
         }
 
-        _app = (char *)malloc(_appLen + 1);
+        _app = (char *)calloc(_appLen + 1, sizeof(char));
 
         if (_app == NULL) {
             return nil;
@@ -862,7 +862,7 @@ static DDTTYLogger *sharedInstance;
         _processID = [NSString stringWithFormat:@"%i", (int)getpid()];
 
         _pidLen = [_processID lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
-        _pid = (char *)malloc(_pidLen + 1);
+        _pid = (char *)calloc(_pidLen + 1, sizeof(char));
 
         if (_pid == NULL) {
             free(_app);
@@ -1211,7 +1211,7 @@ static DDTTYLogger *sharedInstance;
         const BOOL useStack = msgLen < (1024 * 4);
 
         char msgStack[useStack ? (msgLen + 1) : 1]; // Analyzer doesn't like zero-size array, hence the 1
-        char *msg = useStack ? msgStack : (char *)malloc(msgLen + 1);
+        char *msg = useStack ? msgStack : (char *)calloc(msgLen + 1, sizeof(char));
 
         if (msg == NULL) {
             return;

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDContextFilterLogFormatter.h

@@ -20,7 +20,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 /**
  * This class provides a log formatter that filters log statements from a logging context not on the whitelist.

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDDispatchQueueLogFormatter.h

@@ -20,7 +20,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 /**
  *  Log formatter mode

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDMultiFormatter.h

@@ -20,7 +20,7 @@
     #define DD_LEGACY_MACROS 0
 #endif
 
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 /**
  * This formatter can be used to chain different formatters together.

+ 2 - 2
Carthage/Checkouts/CocoaLumberjack/CocoaLumberjack.podspec

@@ -2,7 +2,7 @@
 Pod::Spec.new do |s|
 
   s.name     = 'CocoaLumberjack'
-  s.version  = '3.5.2'
+  s.version  = '3.5.3'
   s.license  = 'BSD'
   s.summary  = 'A fast & simple, yet powerful & flexible logging framework for Mac and iOS.'
   s.homepage = 'https://github.com/CocoaLumberjack/CocoaLumberjack'
@@ -23,7 +23,7 @@ Pod::Spec.new do |s|
   s.osx.deployment_target     = '10.10'
   s.watchos.deployment_target = '3.0'
   s.tvos.deployment_target    = '9.0'
-  s.swift_version = '4.2'
+  s.swift_version = '5.0'
 
   s.default_subspecs = 'Core'
 

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Framework/Lumberjack/CocoaLumberjack-Info.plist

@@ -17,7 +17,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>3.5.2</string>
+	<string>3.5.3</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Framework/Lumberjack/CocoaLumberjackSwift-Info.plist

@@ -17,7 +17,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>3.5.2</string>
+	<string>3.5.3</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

+ 0 - 30
Carthage/Checkouts/KTVHTTPCache/Framework/KTVHTTPCache.h

@@ -1,30 +0,0 @@
-//
-//  KTVHTTPCache.h
-//  KTVHTTPCache
-//
-//  Created by Single on 2017/8/10.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-FOUNDATION_EXPORT double KTVHTTPCacheVersionNumber;
-FOUNDATION_EXPORT const unsigned char KTVHTTPCacheVersionString[];
-
-#pragma mark - Interface
-
-#import <KTVHTTPCache/KTVHTTPCacheImp.h>
-
-#pragma mark - Data Storage
-
-#import <KTVHTTPCache/KTVHCDataReader.h>
-#import <KTVHTTPCache/KTVHCDataLoader.h>
-#import <KTVHTTPCache/KTVHCDataRequest.h>
-#import <KTVHTTPCache/KTVHCDataResponse.h>
-#import <KTVHTTPCache/KTVHCDataCacheItem.h>
-#import <KTVHTTPCache/KTVHCDataCacheItemZone.h>
-
-#pragma mark - Common
-
-#import <KTVHTTPCache/KTVHCRange.h>
-#import <KTVHTTPCache/KTVHCCommon.h>

+ 0 - 15
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCCommon/KTVHCCommon.h

@@ -1,15 +0,0 @@
-//
-//  KTVHCCommon.h
-//  KTVHTTPCache
-//
-//  Created by Single on 2017/8/17.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-#if defined(__cplusplus)
-#define KTVHTTPCACHE_EXTERN extern "C"
-#else
-#define KTVHTTPCACHE_EXTERN extern
-#endif

+ 0 - 27
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataPrivate.h

@@ -1,27 +0,0 @@
-//
-//  KTVHCDataReaderPrivate.h
-//  KTVHTTPCache
-//
-//  Created by Single on 2017/8/11.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-#import "KTVHCDataCacheItem.h"
-#import "KTVHCDataCacheItemZone.h"
-
-@interface KTVHCDataCacheItem (Private)
-
-+ (instancetype)itemWithURL:(NSURL *)URL
-                totalLength:(long long)totalLength
-                cacheLength:(long long)cacheLength
-                vaildLength:(long long)vaildLength
-                      zones:(NSArray <KTVHCDataCacheItemZone *> *)zones;
-
-@end
-
-@interface KTVHCDataCacheItemZone (Private)
-
-+ (instancetype)itemZoneWithOffset:(long long)offset length:(long long)length;
-
-@end

+ 0 - 25
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataSourceProtocol.h

@@ -1,25 +0,0 @@
-//
-//  KTVHCDataSourceProtocol.h
-//  KTVHTTPCache
-//
-//  Created by Single on 2017/8/11.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-#import "KTVHCRange.h"
-
-@protocol KTVHCDataSourceProtocol <NSObject>
-
-- (KTVHCRange)range;
-
-- (BOOL)didPrepared;
-- (BOOL)didFinished;
-- (BOOL)didClosed;
-
-- (void)prepare;
-- (void)close;
-
-- (NSData *)readDataOfLength:(NSUInteger)length;
-
-@end

+ 0 - 39
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataSourceQueue.h

@@ -1,39 +0,0 @@
-//
-//  KTVHCDataSourceQueue.h
-//  KTVHTTPCache
-//
-//  Created by Single on 2017/8/11.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-#import "KTVHCDataSourceProtocol.h"
-
-@class KTVHCDataFileSource;
-@class KTVHCDataNetworkSource;
-
-@protocol KTVHCDataFileSourceDelegate;
-@protocol KTVHCDataNetworkSourceDelegate;
-
-@interface KTVHCDataSourceQueue : NSObject
-
-+ (instancetype)new NS_UNAVAILABLE;
-- (instancetype)init NS_UNAVAILABLE;
-
-+ (instancetype)sourceQueue;
-
-- (void)putSource:(id<KTVHCDataSourceProtocol>)source;
-- (void)popSource:(id<KTVHCDataSourceProtocol>)source;
-
-- (void)setAllSourceDelegate:(id<KTVHCDataFileSourceDelegate, KTVHCDataNetworkSourceDelegate>)delegate delegateQueue:(dispatch_queue_t)delegateQueue;
-
-- (void)sortSources;
-- (void)closeAllSource;
-
-- (id<KTVHCDataSourceProtocol>)firstSource;
-- (id<KTVHCDataSourceProtocol>)nextSource:(id<KTVHCDataSourceProtocol>)currentSource;
-
-- (KTVHCDataNetworkSource *)firstNetworkSource;
-- (KTVHCDataNetworkSource *)nextNetworkSource:(KTVHCDataNetworkSource *)currentSource;
-
-@end

+ 0 - 152
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataSourceQueue.m

@@ -1,152 +0,0 @@
-//
-//  KTVHCDataSourceQueue.m
-//  KTVHTTPCache
-//
-//  Created by Single on 2017/8/11.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import "KTVHCDataSourceQueue.h"
-#import "KTVHCDataFileSource.h"
-#import "KTVHCDataNetworkSource.h"
-#import "KTVHCLog.h"
-
-@interface KTVHCDataSourceQueue ()
-
-@property (nonatomic, strong) NSMutableArray <id<KTVHCDataSourceProtocol>> * sources;
-
-@end
-
-@implementation KTVHCDataSourceQueue
-
-+ (instancetype)sourceQueue
-{
-    return [[self alloc] init];
-}
-
-- (instancetype)init
-{
-    if (self = [super init])
-    {
-        KTVHCLogAlloc(self);
-        self.sources = [NSMutableArray array];
-    }
-    return self;
-}
-
-- (void)dealloc
-{
-    KTVHCLogDealloc(self);
-}
-
-- (void)putSource:(id<KTVHCDataSourceProtocol>)source
-{
-    if (!source) {
-        return;
-    } {
-        [self.sources addObject:source];
-    }
-}
-
-- (void)popSource:(id<KTVHCDataSourceProtocol>)source
-{
-    if (!source)
-    {
-        return;
-    }
-    if ([self.sources containsObject:source])
-    {
-        [self.sources removeObject:source];
-    }
-}
-
-- (void)setAllSourceDelegate:(id<KTVHCDataFileSourceDelegate, KTVHCDataNetworkSourceDelegate>)delegate delegateQueue:(dispatch_queue_t)delegateQueue
-{
-    for (id <KTVHCDataSourceProtocol> obj in self.sources)
-    {
-        if ([obj isKindOfClass:[KTVHCDataFileSource class]])
-        {
-            KTVHCDataFileSource * source = (KTVHCDataFileSource *)obj;
-            [source setDelegate:delegate delegateQueue:delegateQueue];
-        }
-        else if ([obj isKindOfClass:[KTVHCDataNetworkSource class]])
-        {
-            KTVHCDataNetworkSource * source = (KTVHCDataNetworkSource *)obj;
-            [source setDelegate:delegate delegateQueue:delegateQueue];
-        }
-    }
-}
-
-- (void)sortSources
-{
-    KTVHCLogDataSourceQueue(@"%p, Sort sources - Begin\nSources : %@", self, self.sources);
-    [self.sources sortUsingComparator:^NSComparisonResult(id <KTVHCDataSourceProtocol> obj1, id <KTVHCDataSourceProtocol> obj2) {
-        if (obj1.range.start < obj2.range.start)
-        {
-            return NSOrderedAscending;
-        }
-        return NSOrderedDescending;
-    }];
-    KTVHCLogDataSourceQueue(@"%p, Sort sources - End  \nSources : %@", self, self.sources);
-}
-
-- (void)closeAllSource
-{
-    for (id <KTVHCDataSourceProtocol> obj in self.sources)
-    {
-        [obj close];
-    }
-}
-
-- (id<KTVHCDataSourceProtocol>)firstSource
-{
-    return self.sources.firstObject;
-}
-
-- (id<KTVHCDataSourceProtocol>)nextSource:(id<KTVHCDataSourceProtocol>)currentSource
-{
-    if ([self.sources containsObject:currentSource])
-    {
-        NSUInteger index = [self.sources indexOfObject:currentSource] + 1;
-        if (index < self.sources.count)
-        {
-            KTVHCLogDataSourceQueue(@"%p, Fetch next source : %@", self, [self.sources objectAtIndex:index]);
-            return [self.sources objectAtIndex:index];
-        }
-    }
-    KTVHCLogDataSourceQueue(@"%p, Fetch netxt source failed", self);
-    return nil;
-}
-
-- (KTVHCDataNetworkSource *)firstNetworkSource
-{
-    for (id<KTVHCDataSourceProtocol> obj in self.sources)
-    {
-        if ([obj isKindOfClass:[KTVHCDataNetworkSource class]])
-        {
-            return obj;
-        }
-    }
-    return nil;
-}
-
-- (KTVHCDataNetworkSource *)nextNetworkSource:(KTVHCDataNetworkSource *)currentSource
-{
-    if ([self.sources containsObject:currentSource])
-    {
-        NSUInteger index = [self.sources indexOfObject:currentSource] + 1;
-        for (; index < self.sources.count; index++)
-        {
-            id <KTVHCDataSourceProtocol> obj = [self.sources objectAtIndex:index];
-            if ([obj isKindOfClass:[KTVHCDataNetworkSource class]])
-            {
-                KTVHCLogDataSourceQueue(@"%p, Fetch next network source : %@", self, obj);
-                return obj;
-            }
-        }
-    }
-    KTVHCLogDataSourceQueue(@"%p, Fetch netxt network source failed", self);
-    return nil;
-}
-
-@end

+ 0 - 24
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPPingResponse.h

@@ -1,24 +0,0 @@
-//
-//  KTVHCHTTPPingResponse.h
-//  KTVHTTPCache
-//
-//  Created by Single on 2017/10/23.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-#import "KTVHCHTTPHeader.h"
-#import "KTVHCCommon.h"
-
-@class KTVHCHTTPConnection;
-
-KTVHTTPCACHE_EXTERN NSString * const KTVHCHTTPPingResponseResponseValue;
-
-@interface KTVHCHTTPPingResponse : NSObject <HTTPResponse>
-
-+ (instancetype)new NS_UNAVAILABLE;
-- (instancetype)init NS_UNAVAILABLE;
-
-+ (instancetype)responseWithConnection:(KTVHCHTTPConnection *)connection;
-
-@end

+ 0 - 98
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPPingResponse.m

@@ -1,98 +0,0 @@
-//
-//  KTVHCHTTPPingResponse.m
-//  KTVHTTPCache
-//
-//  Created by Single on 2017/10/23.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import "KTVHCHTTPPingResponse.h"
-#import "KTVHCHTTPConnection.h"
-#import "KTVHCLog.h"
-
-NSString * const KTVHCHTTPPingResponseResponseValue = @"pang";
-
-@interface KTVHCHTTPPingResponse ()
-
-@property (nonatomic, weak) KTVHCHTTPConnection * connection;
-@property (nonatomic, strong) NSData * responseData;
-@property (nonatomic, assign) long long readOffset;
-
-@end
-
-@implementation KTVHCHTTPPingResponse
-
-+ (instancetype)responseWithConnection:(KTVHCHTTPConnection *)connection
-{
-    return [[self alloc] initWithConnection:connection];
-}
-
-- (instancetype)initWithConnection:(KTVHCHTTPConnection *)connection
-{
-    if (self = [super init])
-    {
-        KTVHCLogAlloc(self);
-        static NSData * data = nil;
-        static dispatch_once_t onceToken;
-        dispatch_once(&onceToken, ^{
-            data = [KTVHCHTTPPingResponseResponseValue dataUsingEncoding:NSUTF8StringEncoding];
-        });
-        self.responseData = data;
-    }
-    return self;
-}
-
-- (void)dealloc
-{
-    KTVHCLogDealloc(self);
-}
-
-- (NSData *)readDataOfLength:(NSUInteger)length
-{
-    NSData * data = nil;
-    NSUInteger readLength = (NSUInteger)MIN(length, self.responseData.length - self.readOffset);
-    if (readLength == self.responseData.length)
-    {
-        data = self.responseData;
-    }
-    else if (readLength > 0)
-    {
-        data = [self.responseData subdataWithRange:NSMakeRange((NSUInteger)self.readOffset, readLength)];
-    }
-    self.readOffset += data.length;
-    KTVHCLogHTTPResponsePing(@"%p, Read data : %lld", self, (long long)data.length);
-    return data;
-}
-
-- (BOOL)delayResponseHeaders
-{
-    return NO;
-}
-
-- (UInt64)contentLength
-{
-    return self.responseData.length;
-}
-
-- (UInt64)offset
-{
-    return self.readOffset;
-}
-
-- (void)setOffset:(UInt64)offset
-{
-    self.readOffset = offset;
-}
-
-- (BOOL)isDone
-{
-    BOOL result = self.readOffset == self.responseData.length;
-    return result;
-}
-
-- (void)connectionDidClose
-{
-    KTVHCLogHTTPResponsePing(@"%p, Connection did closed", self);
-}
-
-@end

+ 0 - 23
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPRequest.h

@@ -1,23 +0,0 @@
-//
-//  KTVHCHTTPRequest.h
-//  KTVHTTPCache
-//
-//  Created by Single on 2017/8/10.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-@interface KTVHCHTTPRequest : NSObject
-
-+ (instancetype)new NS_UNAVAILABLE;
-- (instancetype)init NS_UNAVAILABLE;
-
-- (instancetype)initWithURL:(NSURL *)URL headers:(NSDictionary *)headers;
-
-@property (nonatomic, copy, readonly) NSURL * URL;
-@property (nonatomic, copy, readonly) NSDictionary * headers;
-@property (nonatomic, copy) NSString * method;
-@property (nonatomic, copy) NSString * version;
-
-@end

+ 0 - 32
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPURL.h

@@ -1,32 +0,0 @@
-//
-//  KTVHCHTTPURL.h
-//  KTVHTTPCache
-//
-//  Created by Single on 2017/8/10.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-typedef NS_ENUM(NSUInteger, KTVHCHTTPURLType)
-{
-    KTVHCHTTPURLTypeUnknown,
-    KTVHCHTTPURLTypeContent,
-    KTVHCHTTPURLTypePing,
-};
-
-@interface KTVHCHTTPURL : NSObject
-
-+ (instancetype)new NS_UNAVAILABLE;
-- (instancetype)init NS_UNAVAILABLE;
-
-+ (instancetype)pingURL;
-- (instancetype)initWithProxyURL:(NSURL *)URL;
-- (instancetype)initWithOriginalURL:(NSURL *)URL;
-
-@property (nonatomic, assign, readonly) KTVHCHTTPURLType type;
-@property (nonatomic, copy, readonly) NSURL * URL;
-
-- (NSURL *)proxyURLWithPort:(NSInteger)port;
-
-@end

+ 0 - 116
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPURL.m

@@ -1,116 +0,0 @@
-//
-//  KTVHCHTTPURL.m
-//  KTVHTTPCache
-//
-//  Created by Single on 2017/8/10.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import "KTVHCHTTPURL.h"
-#import "KTVHCURLTools.h"
-#import "KTVHCLog.h"
-
-static NSString * const kKTVHCHTTPURLRequestURLKey      = @"originalURL";
-static NSString * const kKTVHCHTTPURLRequestTypeKey     = @"requestType";
-static NSString * const kKTVHCHTTPURLRequestTypeContent = @"content";
-static NSString * const kKTVHCHTTPURLRequestTypePing    = @"ping";
-
-@implementation KTVHCHTTPURL
-
-+ (instancetype)pingURL
-{
-    static KTVHCHTTPURL * obj = nil;
-    static dispatch_once_t onceToken;
-    dispatch_once(&onceToken, ^{
-        NSURL * URL = [NSURL URLWithString:@"KTVHTTPCache"];
-        obj = [[KTVHCHTTPURL alloc] initWithOriginalURL:URL];
-        obj->_type = KTVHCHTTPURLTypePing;
-    });
-    return obj;
-}
-
-- (instancetype)initWithProxyURL:(NSURL *)URL
-{
-    if (self = [super init])
-    {
-        KTVHCLogAlloc(self);
-        NSRange requestTypeRange = [URL.absoluteString rangeOfString:[NSString stringWithFormat:@"%@=", kKTVHCHTTPURLRequestTypeKey]];
-        if (requestTypeRange.location != NSNotFound)
-        {
-            NSString * paramString = [URL.absoluteString substringFromIndex:requestTypeRange.location];
-            NSCharacterSet * delimiterSet = [NSCharacterSet characterSetWithCharactersInString:@"&"];
-            NSScanner * scanner = [[NSScanner alloc] initWithString:paramString];
-            while (![scanner isAtEnd])
-            {
-                NSString * tupleString = nil;
-                [scanner scanUpToCharactersFromSet:delimiterSet intoString:&tupleString];
-                [scanner scanCharactersFromSet:delimiterSet intoString:NULL];
-                NSArray <NSString *> * tuple = [tupleString componentsSeparatedByString:@"="];
-                if (tuple.count == 2)
-                {
-                    NSString * key = tuple.firstObject;
-                    NSString * value = tuple.lastObject;
-                    if ([key isEqualToString:kKTVHCHTTPURLRequestURLKey])
-                    {
-                        _URL = [NSURL URLWithString:[KTVHCURLTools URLDecode:value]];
-                    }
-                    else if ([key isEqualToString:kKTVHCHTTPURLRequestTypeKey])
-                    {
-                        if ([value isEqualToString:kKTVHCHTTPURLRequestTypePing])
-                        {
-                            _type = KTVHCHTTPURLTypePing;
-                        }
-                        else if ([value isEqualToString:kKTVHCHTTPURLRequestTypeContent])
-                        {
-                            _type = KTVHCHTTPURLTypeContent;
-                        }
-                    }
-                }
-            }
-        }
-        KTVHCLogHTTPURL(@"%p, Proxy URL\n%@\n%@", self, URL, self.URL);
-    }
-    return self;
-}
-
-- (instancetype)initWithOriginalURL:(NSURL *)URL
-{
-    if (self = [super init])
-    {
-        KTVHCLogAlloc(self);
-        _URL = URL;
-        _type = KTVHCHTTPURLTypeContent;
-        KTVHCLogHTTPURL(@"%p, Original URL\n%@", self, self.URL);
-    }
-    return self;
-}
-
-- (void)dealloc
-{
-    KTVHCLogDealloc(self);
-}
-
-- (NSURL *)proxyURLWithPort:(NSInteger)port
-{
-    NSString * pathExtension = @"";
-    if (self.URL.pathExtension.length > 0)
-    {
-        pathExtension = [NSString stringWithFormat:@".%@", self.URL.pathExtension];
-    }
-    NSString * requestType = kKTVHCHTTPURLRequestTypeContent;
-    if (self.type == KTVHCHTTPURLTypePing)
-    {
-        requestType = kKTVHCHTTPURLRequestTypePing;
-    }
-    NSString * originalURLString = [KTVHCURLTools URLEncode:self.URL.absoluteString];
-    NSString * URLString = [NSString stringWithFormat:@"http://localhost:%d/request%@?%@=%@&%@=%@",
-                            (int)port,
-                            pathExtension,
-                            kKTVHCHTTPURLRequestTypeKey, requestType,
-                            kKTVHCHTTPURLRequestURLKey, originalURLString];
-    NSURL * URL = [NSURL URLWithString:URLString];
-    KTVHCLogHTTPURL(@"%p, Proxy URL\n%@", self, URL);
-    return URL;
-}
-
-@end

+ 0 - 34
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCTools/KTVHCPathTools.h

@@ -1,34 +0,0 @@
-//
-//  KTVHCPathTools.h
-//  KTVHTTPCache
-//
-//  Created by Single on 2017/8/12.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-@interface KTVHCPathTools : NSObject
-
-+ (NSString *)logPath;
-+ (NSString *)archivePath;
-
-+ (NSString *)directoryPathWithURL:(NSURL *)URL;
-+ (NSString *)completeFilePathWithURL:(NSURL *)URL;
-+ (NSString *)unitItemPathWithURL:(NSURL *)URL offset:(long long)offset;
-
-+ (BOOL)isRelativePath:(NSString *)path;
-+ (BOOL)isAbsolutePath:(NSString *)path;
-
-+ (NSString *)relativePathWithAbsoultePath:(NSString *)path;
-+ (NSString *)absoultePathWithRelativePath:(NSString *)path;
-
-+ (void)createFileAtPath:(NSString *)path;
-+ (void)createDirectoryAtPath:(NSString *)path;
-
-+ (NSError *)deleteFileAtPath:(NSString *)path;
-+ (NSError *)deleteDirectoryAtPath:(NSString *)path;
-
-+ (long long)sizeOfItemAtPath:(NSString *)path;
-
-@end

+ 0 - 184
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCTools/KTVHCPathTools.m

@@ -1,184 +0,0 @@
-//
-//  KTVHCPathTools.m
-//  KTVHTTPCache
-//
-//  Created by Single on 2017/8/12.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import "KTVHCPathTools.h"
-#import "KTVHCURLTools.h"
-
-@implementation KTVHCPathTools
-
-+ (NSString *)rootDirectory
-{
-    static NSString * obj = @"KTVHTTPCache";
-    [self createDirectoryAtPath:obj];
-    return obj;
-}
-
-+ (NSString *)logPath
-{
-    NSString * path = [[self rootDirectory] stringByAppendingPathComponent:@"KTVHTTPCache.log"];
-    return [self absoultePathWithRelativePath:path];
-}
-
-+ (NSString *)archivePath
-{
-    NSString * path = [[self rootDirectory] stringByAppendingPathComponent:@"KTVHTTPCache.archive"];
-    return [self absoultePathWithRelativePath:path];
-}
-
-+ (NSString *)directoryPathWithURL:(NSURL *)URL
-{
-    NSString * name = [KTVHCURLTools keyWithURL:URL];
-    NSString * path = [[self rootDirectory] stringByAppendingPathComponent:name];
-    [self createDirectoryAtPath:path];
-    return [self absoultePathWithRelativePath:path];
-}
-
-+ (NSString *)completeFilePathWithURL:(NSURL *)URL
-{
-    NSString * fileName = [KTVHCURLTools keyWithURL:URL];
-    fileName = [fileName stringByAppendingPathExtension:URL.pathExtension];
-    NSString * directoryPath = [self directoryPathWithURL:URL];
-    NSString * filePath = [directoryPath stringByAppendingPathComponent:fileName];
-    return [self absoultePathWithRelativePath:filePath];
-}
-
-+ (NSString *)unitItemPathWithURL:(NSURL *)URL offset:(long long)offset
-{
-    NSString * baseFileName = [KTVHCURLTools keyWithURL:URL];
-    NSString * directoryPath = [self directoryPathWithURL:URL];
-    int number = 0;
-    NSString * filePath = nil;
-    while (!filePath)
-    {
-        NSString * fileName = [NSString stringWithFormat:@"%@_%lld_%d", baseFileName, offset, number];
-        NSString * currentFilePath = [directoryPath stringByAppendingPathComponent:fileName];
-        if (![[NSFileManager defaultManager] fileExistsAtPath:currentFilePath])
-        {
-            [[NSFileManager defaultManager] createFileAtPath:currentFilePath contents:nil attributes:nil];
-            filePath = currentFilePath;
-        }
-        number++;
-    }
-    return [self absoultePathWithRelativePath:filePath];;
-}
-
-+ (NSString *)basePath
-{
-    return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
-}
-
-+ (BOOL)isRelativePath:(NSString *)path
-{
-    return ![path hasPrefix:[self basePath]];
-}
-
-+ (BOOL)isAbsolutePath:(NSString *)path
-{
-    return [path hasPrefix:[self basePath]];
-}
-
-+ (NSString *)relativePathWithAbsoultePath:(NSString *)path
-{
-    if ([self isAbsolutePath:path])
-    {
-        path = [path stringByReplacingOccurrencesOfString:[self basePath] withString:@""];
-    }
-    return path;
-}
-
-+ (NSString *)absoultePathWithRelativePath:(NSString *)path
-{
-    if ([self isRelativePath:path])
-    {
-        path = [[self basePath] stringByAppendingPathComponent:path];;
-    }
-    return path;
-}
-
-+ (void)createFileAtPath:(NSString *)path
-{
-    if (path.length <= 0)
-    {
-        return;
-    }
-    path = [self absoultePathWithRelativePath:path];
-    BOOL isDirectory = NO;
-    BOOL isExists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDirectory];
-    if (!isExists || isDirectory)
-    {
-        [[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil];
-    }
-}
-
-+ (void)createDirectoryAtPath:(NSString *)path
-{
-    if (path.length <= 0)
-    {
-        return;
-    }
-    path = [self absoultePathWithRelativePath:path];
-    BOOL isDirectory = NO;
-    BOOL isExists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDirectory];
-    if (!isExists || !isDirectory)
-    {
-        [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
-    }
-}
-
-+ (NSError *)deleteFileAtPath:(NSString *)path
-{
-    if (path.length <= 0)
-    {
-        return nil;
-    }
-    path = [self absoultePathWithRelativePath:path];
-    NSError * error = nil;
-    BOOL isDirectory = NO;
-    BOOL result = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDirectory];
-    if (result && !isDirectory)
-    {
-        result = [[NSFileManager defaultManager] removeItemAtPath:path error:&error];
-    }
-    return error;
-}
-
-+ (NSError *)deleteDirectoryAtPath:(NSString *)path
-{
-    if (path.length <= 0)
-    {
-        return nil;
-    }
-    path = [self absoultePathWithRelativePath:path];
-    NSError * error = nil;
-    BOOL isDirectory = NO;
-    BOOL result = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDirectory];
-    if (result && isDirectory)
-    {
-        result = [[NSFileManager defaultManager] removeItemAtPath:path error:&error];
-    }
-    return error;
-}
-
-+ (long long)sizeOfItemAtPath:(NSString *)path
-{
-    if (path.length <= 0)
-    {
-        return 0;
-    }
-    path = [self absoultePathWithRelativePath:path];
-    NSError * error;
-    NSDictionary <NSFileAttributeKey, id> * attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:&error];
-    if (!error || attributes.count > 0)
-    {
-        NSNumber * size = [attributes objectForKey:NSFileSize];
-        return size.longLongValue;
-    }
-    return 0;
-}
-
-@end

+ 0 - 27
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCTools/KTVHCURLTools.h

@@ -1,27 +0,0 @@
-//
-//  KTVHCURLTools.h
-//  KTVHTTPCache
-//
-//  Created by Single on 2017/8/10.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-typedef NSURL * (^KTVHCURLFilter)(NSURL * URL);
-
-@interface KTVHCURLTools : NSObject
-
-+ (instancetype)new NS_UNAVAILABLE;
-- (instancetype)init NS_UNAVAILABLE;
-
-+ (instancetype)URLTools;
-
-@property (nonatomic, copy) KTVHCURLFilter URLFilter;
-
-+ (NSString *)keyWithURL:(NSURL *)URL;
-
-+ (NSString *)URLEncode:(NSString *)URLString;
-+ (NSString *)URLDecode:(NSString *)URLString;
-
-@end

+ 0 - 145
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCTools/KTVHCURLTools.m

@@ -1,145 +0,0 @@
-//
-//  KTVHCURLTools.m
-//  KTVHTTPCache
-//
-//  Created by Single on 2017/8/10.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import "KTVHCURLTools.h"
-#import <CommonCrypto/CommonCrypto.h>
-
-@implementation KTVHCURLTools
-
-+ (instancetype)URLTools
-{
-    static KTVHCURLTools * obj = nil;
-    static dispatch_once_t onceToken;
-    dispatch_once(&onceToken, ^{
-        obj = [[self alloc] init];
-    });
-    return obj;
-}
-
-- (NSURL *)URLThroughURLFilter:(NSURL *)URL
-{
-    if (self.URLFilter && URL.absoluteString.length > 0)
-    {
-        NSURL * retURL = self.URLFilter(URL);
-        if (retURL.absoluteString.length > 0)
-        {
-            return retURL;
-        }
-    }
-    return URL;
-}
-
-+ (NSString *)keyWithURL:(NSURL *)URL
-{
-    URL = [[KTVHCURLTools URLTools] URLThroughURLFilter:URL];
-    return [self md5:URL.absoluteString];
-}
-
-+ (NSString *)md5:(NSString *)URLString
-{
-    const char * value = [URLString UTF8String];
-    unsigned char outputBuffer[CC_MD5_DIGEST_LENGTH];
-    CC_MD5(value, (CC_LONG)strlen(value), outputBuffer);
-    NSMutableString * outputString = [[NSMutableString alloc] initWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
-    for (NSInteger count = 0; count < CC_MD5_DIGEST_LENGTH; count++)
-    {
-        [outputString appendFormat:@"%02x", outputBuffer[count]];
-    }
-    return outputString;
-}
-
-+ (NSString *)base64Encode:(NSString *)URLString
-{
-    NSData * data = [URLString dataUsingEncoding:NSUTF8StringEncoding];
-    return [data base64EncodedStringWithOptions:0];
-}
-
-+ (NSString *)base64Decode:(NSString *)URLString
-{
-    NSData * data = [[NSData alloc] initWithBase64EncodedString:URLString options:0];
-    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
-}
-
-+ (NSString *)URLEncode:(NSString *)URLString
-{
-    URLString = [URLString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
-    NSUInteger length = [URLString length];
-    const char * c = [URLString UTF8String];
-    NSString * resultString = @"";
-    for(int i = 0; i < length; i++)
-    {
-        switch (*c)
-        {
-            case '/':
-                resultString = [resultString stringByAppendingString:@"%2F"];
-                break;
-            case '\'':
-                resultString = [resultString stringByAppendingString:@"%27"];
-                break;
-            case ';':
-                resultString = [resultString stringByAppendingString:@"%3B"];
-                break;
-            case '?':
-                resultString = [resultString stringByAppendingString:@"%3F"];
-                break;
-            case ':':
-                resultString = [resultString stringByAppendingString:@"%3A"];
-                break;
-            case '@':
-                resultString = [resultString stringByAppendingString:@"%40"];
-                break;
-            case '&':
-                resultString = [resultString stringByAppendingString:@"%26"];
-                break;
-            case '=':
-                resultString = [resultString stringByAppendingString:@"%3D"];
-                break;
-            case '+':
-                resultString = [resultString stringByAppendingString:@"%2B"];
-                break;
-            case '$':
-                resultString = [resultString stringByAppendingString:@"%24"];
-                break;
-            case ',':
-                resultString = [resultString stringByAppendingString:@"%2C"];
-                break;
-            case '[':
-                resultString = [resultString stringByAppendingString:@"%5B"];
-                break;
-            case ']':
-                resultString = [resultString stringByAppendingString:@"%5D"];
-                break;
-            case '#':
-                resultString = [resultString stringByAppendingString:@"%23"];
-                break;
-            case '!':
-                resultString = [resultString stringByAppendingString:@"%21"];
-                break;
-            case '(':
-                resultString = [resultString stringByAppendingString:@"%28"];
-                break;
-            case ')':
-                resultString = [resultString stringByAppendingString:@"%29"];
-                break;
-            case '*':
-                resultString = [resultString stringByAppendingString:@"%2A"];
-                break;
-            default:
-                resultString = [resultString stringByAppendingFormat:@"%c", *c];
-        }
-        c++;
-    }
-    return resultString;
-}
-
-+ (NSString *)URLDecode:(NSString *)URLString
-{
-    return [URLString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
-}
-
-@end

+ 0 - 139
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHTTPCacheImp.h

@@ -1,139 +0,0 @@
-//
-//  KTVHTTPCacheImp.h
-//  KTVHTTPCache
-//
-//  Created by Single on 2017/8/13.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-@class KTVHCDataReader;
-@class KTVHCDataLoader;
-@class KTVHCDataRequest;
-@class KTVHCDataCacheItem;
-
-@interface KTVHTTPCache : NSObject
-
-#pragma mark - HTTP Server
-
-/**
- *  Start & Stop HTTP Server.
- */
-+ (void)proxyStart:(NSError **)error;
-+ (void)proxyStop;
-
-+ (BOOL)proxyIsRunning;
-
-/**
- *  Return the URL string for local server.
- */
-+ (NSURL *)proxyURLWithOriginalURL:(NSURL *)URL;
-+ (NSString *)proxyURLStringWithOriginalURLString:(NSString *)URLString;
-
-#pragma mark - Data Storage
-
-/**
- *  If the content of the URL is finish cached, return the file path for the content. Otherwise return nil.
- */
-+ (NSURL *)cacheCompleteFileURLIfExistedWithURL:(NSURL *)URL;
-+ (NSString *)cacheCompleteFilePathIfExistedWithURLString:(NSString *)URLString;
-
-/**
- *  Data Reader.
- */
-+ (KTVHCDataReader *)cacheReaderWithRequest:(KTVHCDataRequest *)request;
-
-/**
- *  Data Loader.
- */
-+ (KTVHCDataLoader *)cacheLoaderWithRequest:(KTVHCDataRequest *)request;
-
-/**
- *  Cache State.
- */
-+ (void)cacheSetMaxCacheLength:(long long)maxCacheLength;
-+ (long long)cacheMaxCacheLength;
-+ (long long)cacheTotalCacheLength;
-
-/**
- *  Cache Item.
- */
-+ (KTVHCDataCacheItem *)cacheCacheItemWithURL:(NSURL *)URL;
-+ (KTVHCDataCacheItem *)cacheCacheItemWithURLString:(NSString *)URLString;
-+ (NSArray <KTVHCDataCacheItem *> *)cacheAllCacheItems;
-
-/**
- *  Delete Cache.
- */
-+ (void)cacheDeleteCacheWithURL:(NSURL *)URL;
-+ (void)cacheDeleteCacheWithURLString:(NSString *)URLString;
-+ (void)cacheDeleteAllCaches;
-
-#pragma mark - Token
-
-/**
- *  URL Filter.
- *
- *  High frequency call. Make it simple.
- */
-+ (void)tokenSetURLFilter:(NSURL * (^)(NSURL * URL))URLFilter;
-
-#pragma mark - Download
-
-+ (void)downloadSetTimeoutInterval:(NSTimeInterval)timeoutInterval;
-+ (NSTimeInterval)downloadTimeoutInterval;
-
-/**
- *  Whitelist Header Fields.
- */
-+ (void)downloadSetWhitelistHeaderKeys:(NSArray <NSString *> *)whitelistHeaderKeys;
-+ (NSArray <NSString *> *)downloadWhitelistHeaderKeys;
-
-/**
- *  Additional Header Fields.
- */
-+ (void)downloadSetAdditionalHeaders:(NSDictionary <NSString *, NSString *> *)additionalHeaders;
-+ (NSDictionary <NSString *, NSString *> *)downloadAdditionalHeaders;
-
-/**
- *  Default values: 'video/x', 'audio/x', 'application/mp4', 'application/octet-stream', 'binary/octet-stream'
- */
-+ (void)downloadSetAcceptContentTypes:(NSArray <NSString *> *)acceptContentTypes;
-+ (NSArray <NSString *> *)downloadAcceptContentTypes;
-
-/**
- *  If the receive response's Content-Type not included in acceptContentTypes, this method will be called.
- *  The return value of block to decide whether to continue to load resources. Otherwise the HTTP task will be rejected.
- */
-+ (void)downloadSetUnsupportContentTypeFilter:(BOOL(^)(NSURL * URL, NSString * contentType))contentTypeFilter;
-
-#pragma mark - Log
-
-/**
- *  Console & Record.
- */
-+ (void)logAddLog:(NSString *)log;
-
-/**
- *  DEBUG & RELEASE : Default is NO.
- */
-+ (void)logSetConsoleLogEnable:(BOOL)consoleLogEnable;
-+ (BOOL)logConsoleLogEnable;
-
-/**
- *  DEBUG & RELEASE : Default is NO.
- */
-+ (void)logSetRecordLogEnable:(BOOL)recordLogEnable;
-+ (BOOL)logRecordLogEnable;
-
-+ (NSString *)logRecordLogFilePath;      // nullable
-+ (void)logDeleteRecordLog;
-
-/**
- *  Error
- */
-+ (NSArray <NSError *> *)logAllErrors;
-+ (NSError *)logLastError;
-
-@end

+ 0 - 224
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHTTPCacheImp.m

@@ -1,224 +0,0 @@
-//
-//  KTVHTTPCacheImp.m
-//  KTVHTTPCache
-//
-//  Created by Single on 2017/8/13.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import "KTVHTTPCacheImp.h"
-#import "KTVHCHTTPServer.h"
-#import "KTVHCDataStorage.h"
-#import "KTVHCDownload.h"
-#import "KTVHCURLTools.h"
-#import "KTVHCLog.h"
-
-@implementation KTVHTTPCache
-
-#pragma mark - HTTP Server
-
-+ (void)proxyStart:(NSError * __autoreleasing *)error
-{
-    [[KTVHCHTTPServer server] start:error];
-}
-
-+ (void)proxyStop
-{
-    [[KTVHCHTTPServer server] stop];
-}
-
-+ (BOOL)proxyIsRunning
-{
-    return [KTVHCHTTPServer server].running;
-}
-
-+ (NSURL *)proxyURLWithOriginalURL:(NSURL *)URL
-{
-    URL = [[KTVHCHTTPServer server] URLWithOriginalURL:URL];
-    return URL;
-}
-
-+ (NSString *)proxyURLStringWithOriginalURLString:(NSString *)URLString
-{
-    NSURL * URL = [NSURL URLWithString:URLString];
-    URL = [[KTVHCHTTPServer server] URLWithOriginalURL:URL];
-    return URL.absoluteString;
-}
-
-#pragma mark - Data Storage
-
-+ (NSURL *)cacheCompleteFileURLIfExistedWithURL:(NSURL *)URL
-{
-    URL = [[KTVHCDataStorage storage] completeFileURLIfExistedWithURL:URL];
-    return URL;
-}
-
-+ (NSString *)cacheCompleteFilePathIfExistedWithURLString:(NSString *)URLString
-{
-    NSURL * URL = [NSURL URLWithString:URLString];
-    URL = [[KTVHCDataStorage storage] completeFileURLIfExistedWithURL:URL];
-    return URL.path;
-}
-
-+ (KTVHCDataReader *)cacheReaderWithRequest:(KTVHCDataRequest *)request
-{
-    return [[KTVHCDataStorage storage] readerWithRequest:request];
-}
-
-+ (KTVHCDataLoader *)cacheLoaderWithRequest:(KTVHCDataRequest *)request
-{
-    return [[KTVHCDataStorage storage] loaderWithRequest:request];
-}
-
-+ (void)cacheSetMaxCacheLength:(long long)maxCacheLength
-{
-    [KTVHCDataStorage storage].maxCacheLength = maxCacheLength;
-}
-
-+ (long long)cacheMaxCacheLength
-{
-    return [KTVHCDataStorage storage].maxCacheLength;
-}
-
-+ (long long)cacheTotalCacheLength
-{
-    return [KTVHCDataStorage storage].totalCacheLength;
-}
-
-+ (KTVHCDataCacheItem *)cacheCacheItemWithURL:(NSURL *)URL
-{
-    return [[KTVHCDataStorage storage] cacheItemWithURL:URL];
-}
-
-+ (KTVHCDataCacheItem *)cacheCacheItemWithURLString:(NSString *)URLString
-{
-    NSURL * URL = [NSURL URLWithString:URLString];
-    return [[KTVHCDataStorage storage] cacheItemWithURL:URL];
-}
-
-+ (NSArray<KTVHCDataCacheItem *> *)cacheAllCacheItems
-{
-    return [[KTVHCDataStorage storage] allCacheItems];
-}
-
-+ (void)cacheDeleteCacheWithURL:(NSURL *)URL
-{
-    [[KTVHCDataStorage storage] deleteCacheWithURL:URL];
-}
-
-+ (void)cacheDeleteCacheWithURLString:(NSString *)URLString
-{
-    NSURL * URL = [NSURL URLWithString:URLString];
-    [[KTVHCDataStorage storage] deleteCacheWithURL:URL];
-}
-
-+ (void)cacheDeleteAllCaches
-{
-    [[KTVHCDataStorage storage] deleteAllCaches];
-}
-
-#pragma mark - Token
-
-+ (void)tokenSetURLFilter:(NSURL * (^)(NSURL * URL))URLFilter
-{
-    [KTVHCURLTools URLTools].URLFilter = URLFilter;
-}
-
-#pragma mark - Download
-
-+ (void)downloadSetTimeoutInterval:(NSTimeInterval)timeoutInterval
-{
-    [KTVHCDownload download].timeoutInterval = timeoutInterval;
-}
-
-+ (NSTimeInterval)downloadTimeoutInterval
-{
-    return [KTVHCDownload download].timeoutInterval;
-}
-
-+ (void)downloadSetWhitelistHeaderKeys:(NSArray <NSString *> *)whitelistHeaderKeys
-{
-    [KTVHCDownload download].whitelistHeaderKeys = whitelistHeaderKeys;
-}
-
-+ (NSArray <NSString *> *)downloadWhitelistHeaderKeys
-{
-    return [KTVHCDownload download].whitelistHeaderKeys;
-}
-
-+ (void)downloadSetAdditionalHeaders:(NSDictionary <NSString *, NSString *> *)additionalHeaders
-{
-    [KTVHCDownload download].additionalHeaders = additionalHeaders;
-}
-
-+ (NSDictionary <NSString *, NSString *> *)downloadAdditionalHeaders
-{
-    return [KTVHCDownload download].additionalHeaders;
-}
-
-+ (void)downloadSetAcceptContentTypes:(NSArray <NSString *> *)acceptContentTypes
-{
-    [KTVHCDownload download].acceptContentTypes = acceptContentTypes;
-}
-
-+ (NSArray <NSString *> *)downloadAcceptContentTypes
-{
-    return [KTVHCDownload download].acceptContentTypes;
-}
-
-+ (void)downloadSetUnsupportContentTypeFilter:(BOOL(^)(NSURL * URL, NSString * contentType))contentTypeFilter
-{
-    [KTVHCDownload download].unsupportContentTypeFilter = contentTypeFilter;
-}
-
-#pragma mark - Log
-
-+ (void)logAddLog:(NSString *)log
-{
-    if (log.length > 0)
-    {
-        KTVHCLogCommon(@"%@", log);
-    }
-}
-
-+ (void)logSetConsoleLogEnable:(BOOL)consoleLogEnable
-{
-    [KTVHCLog log].consoleLogEnable = consoleLogEnable;
-}
-
-+ (BOOL)logConsoleLogEnable
-{
-    return [KTVHCLog log].consoleLogEnable;
-}
-
-+ (BOOL)logRecordLogEnable
-{
-    return [KTVHCLog log].recordLogEnable;
-}
-
-+ (NSString *)logRecordLogFilePath
-{
-    return [KTVHCLog log].recordLogFilePath;
-}
-
-+ (void)logSetRecordLogEnable:(BOOL)recordLogEnable
-{
-    [KTVHCLog log].recordLogEnable = recordLogEnable;
-}
-
-+ (void)logDeleteRecordLog
-{
-    [[KTVHCLog log] deleteRecordLog];
-}
-
-+ (NSArray<NSError *> *)logAllErrors
-{
-    return [[KTVHCLog log] allErrors];
-}
-
-+ (NSError *)logLastError
-{
-    return [[KTVHCLog log] lastError];
-}
-
-@end

+ 0 - 16
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/AppDelegate.h

@@ -1,16 +0,0 @@
-//
-//  AppDelegate.h
-//  KTVHTTPCacheDemo
-//
-//  Created by Single on 2017/8/10.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface AppDelegate : UIResponder <UIApplicationDelegate>
-
-@property (strong, nonatomic) UIWindow * window;
-
-@end
-

+ 0 - 17
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/AppDelegate.m

@@ -1,17 +0,0 @@
-//
-//  AppDelegate.m
-//  KTVHTTPCacheDemo
-//
-//  Created by Single on 2017/8/10.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import "AppDelegate.h"
-
-@interface AppDelegate ()
-
-@end
-
-@implementation AppDelegate
-
-@end

+ 0 - 38
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Assets.xcassets/AppIcon.appiconset/Contents.json

@@ -1,38 +0,0 @@
-{
-  "images" : [
-    {
-      "idiom" : "iphone",
-      "size" : "29x29",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "29x29",
-      "scale" : "3x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "40x40",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "40x40",
-      "scale" : "3x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "60x60",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "60x60",
-      "scale" : "3x"
-    }
-  ],
-  "info" : {
-    "version" : 1,
-    "author" : "xcode"
-  }
-}

+ 0 - 27
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Base.lproj/LaunchScreen.storyboard

@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
-    <dependencies>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <scenes>
-        <!--View Controller-->
-        <scene sceneID="EHf-IW-A2E">
-            <objects>
-                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
-                    <layoutGuides>
-                        <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
-                        <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
-                    </layoutGuides>
-                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
-                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
-                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                    </view>
-                </viewController>
-                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
-            </objects>
-            <point key="canvasLocation" x="53" y="375"/>
-        </scene>
-    </scenes>
-</document>

+ 0 - 203
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Base.lproj/Main.storyboard

@@ -1,203 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="mKc-CQ-Vkb">
-    <device id="retina4_7" orientation="portrait">
-        <adaptation id="fullscreen"/>
-    </device>
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
-        <capability name="Alignment constraints with different attributes" minToolsVersion="5.1"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <scenes>
-        <!--KTV-->
-        <scene sceneID="tne-QT-ifu">
-            <objects>
-                <viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
-                    <layoutGuides>
-                        <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
-                        <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
-                    </layoutGuides>
-                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
-                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
-                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                        <subviews>
-                            <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" translatesAutoresizingMaskIntoConstraints="NO" id="iES-3w-2ag">
-                                <rect key="frame" x="0.0" y="0.0" width="375" height="618"/>
-                                <color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
-                                <prototypes>
-                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="MediaCell" id="Ndt-7i-Uno" customClass="MediaCell">
-                                        <rect key="frame" x="0.0" y="55.5" width="375" height="44"/>
-                                        <autoresizingMask key="autoresizingMask"/>
-                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Ndt-7i-Uno" id="hB8-d7-Ud0">
-                                            <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
-                                            <autoresizingMask key="autoresizingMask"/>
-                                            <subviews>
-                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Media Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="IYc-St-ffs">
-                                                    <rect key="frame" x="22" y="11" width="331" height="21"/>
-                                                    <constraints>
-                                                        <constraint firstAttribute="height" constant="21" id="5nd-3B-0Hh"/>
-                                                    </constraints>
-                                                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                                                    <nil key="textColor"/>
-                                                    <nil key="highlightedColor"/>
-                                                </label>
-                                            </subviews>
-                                            <constraints>
-                                                <constraint firstItem="IYc-St-ffs" firstAttribute="leading" secondItem="hB8-d7-Ud0" secondAttribute="leading" constant="22" id="4Zi-Ev-sy1"/>
-                                                <constraint firstAttribute="trailing" secondItem="IYc-St-ffs" secondAttribute="trailing" constant="22" id="DzP-po-T9b"/>
-                                                <constraint firstItem="IYc-St-ffs" firstAttribute="centerY" secondItem="hB8-d7-Ud0" secondAttribute="centerY" id="mRz-th-Is1"/>
-                                            </constraints>
-                                        </tableViewCellContentView>
-                                        <connections>
-                                            <outlet property="titleLabel" destination="IYc-St-ffs" id="iCt-mT-Sxw"/>
-                                        </connections>
-                                    </tableViewCell>
-                                </prototypes>
-                                <connections>
-                                    <outlet property="dataSource" destination="BYZ-38-t0r" id="pWu-GL-K7k"/>
-                                    <outlet property="delegate" destination="BYZ-38-t0r" id="lj7-Gf-zPP"/>
-                                </connections>
-                            </tableView>
-                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hHe-LP-d6F">
-                                <rect key="frame" x="0.0" y="618" width="375" height="49"/>
-                                <constraints>
-                                    <constraint firstAttribute="height" constant="49" id="ilC-p7-TCA"/>
-                                </constraints>
-                                <state key="normal" title="Check Cache State"/>
-                                <connections>
-                                    <segue destination="OX5-Lb-bJb" kind="show" id="AHt-m0-ShY"/>
-                                </connections>
-                            </button>
-                        </subviews>
-                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                        <constraints>
-                            <constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="hHe-LP-d6F" secondAttribute="bottom" id="6VD-M4-Ydd"/>
-                            <constraint firstItem="hHe-LP-d6F" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="7tz-qa-3bg"/>
-                            <constraint firstAttribute="trailing" secondItem="hHe-LP-d6F" secondAttribute="trailing" id="Esf-cD-HuW"/>
-                            <constraint firstItem="hHe-LP-d6F" firstAttribute="top" secondItem="iES-3w-2ag" secondAttribute="bottom" id="Jgm-7D-UU1"/>
-                            <constraint firstAttribute="trailing" secondItem="iES-3w-2ag" secondAttribute="trailing" id="Nab-Hd-4ma"/>
-                            <constraint firstItem="iES-3w-2ag" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="fdD-jQ-rkd"/>
-                            <constraint firstItem="iES-3w-2ag" firstAttribute="top" secondItem="8bC-Xf-vdC" secondAttribute="top" id="i4K-zN-l9p"/>
-                        </constraints>
-                    </view>
-                    <navigationItem key="navigationItem" title="KTV" id="yeW-NV-LD9"/>
-                    <connections>
-                        <outlet property="tableView" destination="iES-3w-2ag" id="gxb-Yy-8xw"/>
-                    </connections>
-                </viewController>
-                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
-            </objects>
-            <point key="canvasLocation" x="1055.2" y="102.99850074962519"/>
-        </scene>
-        <!--Cache-->
-        <scene sceneID="0j5-Rv-GtJ">
-            <objects>
-                <viewController title="Cache" id="OX5-Lb-bJb" customClass="CacheViewController" sceneMemberID="viewController">
-                    <layoutGuides>
-                        <viewControllerLayoutGuide type="top" id="5rr-fK-cG2"/>
-                        <viewControllerLayoutGuide type="bottom" id="PhN-Ef-fs4"/>
-                    </layoutGuides>
-                    <view key="view" contentMode="scaleToFill" id="R79-DI-1uC">
-                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
-                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                        <subviews>
-                            <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" translatesAutoresizingMaskIntoConstraints="NO" id="Had-oU-RyV">
-                                <rect key="frame" x="0.0" y="0.0" width="375" height="618"/>
-                                <color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
-                                <prototypes>
-                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="CacheItemZoneCell" id="4c6-wC-jrf" customClass="CacheItemZoneCell">
-                                        <rect key="frame" x="0.0" y="55.5" width="375" height="44"/>
-                                        <autoresizingMask key="autoresizingMask"/>
-                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="4c6-wC-jrf" id="x12-Dm-b4R">
-                                            <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
-                                            <autoresizingMask key="autoresizingMask"/>
-                                            <subviews>
-                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Offset :" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fEw-79-dlN">
-                                                    <rect key="frame" x="22" y="11" width="165.5" height="21"/>
-                                                    <constraints>
-                                                        <constraint firstAttribute="height" constant="21" id="eHd-xP-XTW"/>
-                                                    </constraints>
-                                                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                                                    <nil key="textColor"/>
-                                                    <nil key="highlightedColor"/>
-                                                </label>
-                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Length :" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dQg-Rv-4MR">
-                                                    <rect key="frame" x="188" y="13" width="165" height="17"/>
-                                                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                                                    <nil key="textColor"/>
-                                                    <nil key="highlightedColor"/>
-                                                </label>
-                                            </subviews>
-                                            <constraints>
-                                                <constraint firstItem="dQg-Rv-4MR" firstAttribute="centerY" secondItem="fEw-79-dlN" secondAttribute="centerY" id="9c2-bo-ZEA"/>
-                                                <constraint firstItem="fEw-79-dlN" firstAttribute="trailing" secondItem="x12-Dm-b4R" secondAttribute="centerX" id="VUv-3U-bKQ"/>
-                                                <constraint firstItem="fEw-79-dlN" firstAttribute="centerY" secondItem="x12-Dm-b4R" secondAttribute="centerY" id="hYd-1f-JmX"/>
-                                                <constraint firstAttribute="trailing" secondItem="dQg-Rv-4MR" secondAttribute="trailing" constant="22" id="kEe-Xf-fAX"/>
-                                                <constraint firstItem="dQg-Rv-4MR" firstAttribute="leading" secondItem="x12-Dm-b4R" secondAttribute="centerX" id="p5P-Ed-xYC"/>
-                                                <constraint firstItem="fEw-79-dlN" firstAttribute="leading" secondItem="x12-Dm-b4R" secondAttribute="leading" constant="22" id="vAC-NH-PBr"/>
-                                            </constraints>
-                                        </tableViewCellContentView>
-                                        <connections>
-                                            <outlet property="lengthLabel" destination="dQg-Rv-4MR" id="JG4-ad-3Lp"/>
-                                            <outlet property="offsetLabel" destination="fEw-79-dlN" id="jfv-de-t1O"/>
-                                        </connections>
-                                    </tableViewCell>
-                                </prototypes>
-                                <connections>
-                                    <outlet property="dataSource" destination="OX5-Lb-bJb" id="S3B-QY-v66"/>
-                                    <outlet property="delegate" destination="OX5-Lb-bJb" id="jt1-nS-k1v"/>
-                                </connections>
-                            </tableView>
-                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="nzd-Ut-bbk">
-                                <rect key="frame" x="0.0" y="618" width="375" height="49"/>
-                                <constraints>
-                                    <constraint firstAttribute="height" constant="49" id="6bP-I2-zfD"/>
-                                </constraints>
-                                <state key="normal" title="Delete All Cache">
-                                    <color key="titleColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
-                                </state>
-                                <connections>
-                                    <action selector="deleteAllCache:" destination="OX5-Lb-bJb" eventType="touchUpInside" id="Kwy-de-P7u"/>
-                                </connections>
-                            </button>
-                        </subviews>
-                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
-                        <constraints>
-                            <constraint firstItem="Had-oU-RyV" firstAttribute="top" secondItem="R79-DI-1uC" secondAttribute="top" id="0eR-hL-b4N"/>
-                            <constraint firstAttribute="trailing" secondItem="Had-oU-RyV" secondAttribute="trailing" id="7CY-9M-BBo"/>
-                            <constraint firstItem="Had-oU-RyV" firstAttribute="leading" secondItem="R79-DI-1uC" secondAttribute="leading" id="9cR-Xl-dhT"/>
-                            <constraint firstItem="PhN-Ef-fs4" firstAttribute="top" secondItem="nzd-Ut-bbk" secondAttribute="bottom" id="LaV-Ib-EqM"/>
-                            <constraint firstItem="nzd-Ut-bbk" firstAttribute="leading" secondItem="R79-DI-1uC" secondAttribute="leading" id="eNH-Cd-Y7d"/>
-                            <constraint firstItem="nzd-Ut-bbk" firstAttribute="top" secondItem="Had-oU-RyV" secondAttribute="bottom" id="pEQ-Kb-KHD"/>
-                            <constraint firstAttribute="trailing" secondItem="nzd-Ut-bbk" secondAttribute="trailing" id="uBf-hm-S2b"/>
-                        </constraints>
-                    </view>
-                    <connections>
-                        <outlet property="tableView" destination="Had-oU-RyV" id="OwD-GY-dH0"/>
-                    </connections>
-                </viewController>
-                <placeholder placeholderIdentifier="IBFirstResponder" id="hcD-P4-Pp2" userLabel="First Responder" sceneMemberID="firstResponder"/>
-            </objects>
-            <point key="canvasLocation" x="1935.2" y="102.99850074962519"/>
-        </scene>
-        <!--Navigation Controller-->
-        <scene sceneID="mc3-Ec-LhP">
-            <objects>
-                <navigationController automaticallyAdjustsScrollViewInsets="NO" id="mKc-CQ-Vkb" sceneMemberID="viewController">
-                    <toolbarItems/>
-                    <navigationBar key="navigationBar" contentMode="scaleToFill" id="brt-DP-6OK">
-                        <rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
-                        <autoresizingMask key="autoresizingMask"/>
-                    </navigationBar>
-                    <nil name="viewControllers"/>
-                    <connections>
-                        <segue destination="BYZ-38-t0r" kind="relationship" relationship="rootViewController" id="kFj-KT-jQs"/>
-                    </connections>
-                </navigationController>
-                <placeholder placeholderIdentifier="IBFirstResponder" id="XO5-Nk-rPd" userLabel="First Responder" sceneMemberID="firstResponder"/>
-            </objects>
-            <point key="canvasLocation" x="116" y="102.99850074962519"/>
-        </scene>
-    </scenes>
-</document>

+ 0 - 27
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Cache/CacheItemView.h

@@ -1,27 +0,0 @@
-//
-//  CacheItemView.h
-//  KTVHTTPCacheDemo
-//
-//  Created by Single on 2017/8/13.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@class CacheItemView;
-
-@protocol  CacheItemViewDelegate <NSObject>
-
-- (void)cacheItemView:(CacheItemView *)view deleteButtonDidClick:(NSString *)URLString;
-
-@end
-
-@interface CacheItemView : UIView
-
-- (instancetype)initWithURLString:(NSString *)URLString
-                      totalLength:(long long)totalLength
-                      cacheLength:(long long)cacheLength;
-
-@property (nonatomic, weak) id <CacheItemViewDelegate> delegate;
-
-@end

+ 0 - 89
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Cache/CacheItemView.m

@@ -1,89 +0,0 @@
-//
-//  CacheItemView.m
-//  KTVHTTPCacheDemo
-//
-//  Created by Single on 2017/8/13.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import "CacheItemView.h"
-
-@interface CacheItemView ()
-
-@property (nonatomic, strong) UILabel * totalLengthLabel;
-@property (nonatomic, strong) UILabel * cacheLengthLabel;
-@property (nonatomic, strong) UILabel * textLabel;
-@property (nonatomic, strong) UIButton * deleteButton;
-
-@end
-
-@implementation CacheItemView
-
-- (instancetype)initWithURLString:(NSString *)URLString
-                      totalLength:(long long)totalLength
-                      cacheLength:(long long)cacheLength
-{
-    if (self = [super initWithFrame:CGRectZero])
-    {
-        self.backgroundColor = [UIColor whiteColor];
-        
-        self.totalLengthLabel = [[UILabel alloc] initWithFrame:CGRectZero];
-        self.totalLengthLabel.textColor = self.totalLengthLabel.tintColor;
-        self.totalLengthLabel.font = [UIFont systemFontOfSize:14];
-        self.totalLengthLabel.text = [NSString stringWithFormat:@"Total Length : %lld", totalLength];
-        
-        self.cacheLengthLabel = [[UILabel alloc] initWithFrame:CGRectZero];
-        self.cacheLengthLabel.textColor = self.cacheLengthLabel.tintColor;
-        self.cacheLengthLabel.font = [UIFont systemFontOfSize:14];
-        self.cacheLengthLabel.text = [NSString stringWithFormat:@"Cache Length : %lld", cacheLength];
-        
-        self.textLabel = [[UILabel alloc] initWithFrame:CGRectZero];
-        self.textLabel.textColor = self.textLabel.tintColor;
-        self.textLabel.font = [UIFont systemFontOfSize:14];
-        self.textLabel.text = URLString;
-        self.textLabel.numberOfLines = 0;
-        
-        self.deleteButton = [[UIButton alloc] initWithFrame:CGRectZero];
-        [self.deleteButton addTarget:self action:@selector(deleteButtonAction) forControlEvents:UIControlEventTouchUpInside];
-        [self.deleteButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
-        [self.deleteButton setTitle:@"Delete" forState:UIControlStateNormal];
-        self.deleteButton.titleLabel.font = [UIFont systemFontOfSize:15];
-        
-        [self addSubview:self.totalLengthLabel];
-        [self addSubview:self.cacheLengthLabel];
-        [self addSubview:self.textLabel];
-        [self addSubview:self.deleteButton];
-    }
-    return self;
-}
-
-- (void)layoutSubviews
-{
-    [super layoutSubviews];
-    
-    self.totalLengthLabel.frame = CGRectMake(20,
-                                             15,
-                                             self.bounds.size.width - 40,
-                                             18);
-    self.cacheLengthLabel.frame = CGRectMake(20,
-                                             33,
-                                             self.bounds.size.width - 40,
-                                             18);
-    self.textLabel.frame = CGRectMake(20,
-                                      CGRectGetMaxY(self.cacheLengthLabel.frame) + 5,
-                                      self.bounds.size.width - 40,
-                                      self.bounds.size.height - 60);
-    self.deleteButton.frame = CGRectMake(self.bounds.size.width - 40 - 80,
-                                         20,
-                                         80,
-                                         26);
-}
-
-- (void)deleteButtonAction
-{
-    if ([self.delegate respondsToSelector:@selector(cacheItemView:deleteButtonDidClick:)]) {
-        [self.delegate cacheItemView:self deleteButtonDidClick:self.textLabel.text];
-    }
-}
-
-@end

+ 0 - 15
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Cache/CacheItemZoneCell.h

@@ -1,15 +0,0 @@
-//
-//  CacheItemZoneCell.h
-//  KTVHTTPCacheDemo
-//
-//  Created by Single on 2017/8/13.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface CacheItemZoneCell : UITableViewCell
-
-- (void)configureWithOffset:(long long)offset length:(long long)length;
-
-@end

+ 0 - 26
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Cache/CacheItemZoneCell.m

@@ -1,26 +0,0 @@
-//
-//  CacheItemZoneCell.m
-//  KTVHTTPCacheDemo
-//
-//  Created by Single on 2017/8/13.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import "CacheItemZoneCell.h"
-
-@interface CacheItemZoneCell ()
-
-@property (weak, nonatomic) IBOutlet UILabel * offsetLabel;
-@property (weak, nonatomic) IBOutlet UILabel * lengthLabel;
-
-@end
-
-@implementation CacheItemZoneCell
-
-- (void)configureWithOffset:(long long)offset length:(long long)length
-{
-    self.offsetLabel.text = [NSString stringWithFormat:@"Offset : %lld", offset];
-    self.lengthLabel.text = [NSString stringWithFormat:@"Length : %lld", length];
-}
-
-@end

+ 0 - 13
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Cache/CacheViewController.h

@@ -1,13 +0,0 @@
-//
-//  CacheViewController.h
-//  KTVHTTPCacheDemo
-//
-//  Created by Single on 2017/8/13.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface CacheViewController : UIViewController
-
-@end

+ 0 - 87
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Cache/CacheViewController.m

@@ -1,87 +0,0 @@
-//
-//  CacheViewController.m
-//  KTVHTTPCacheDemo
-//
-//  Created by Single on 2017/8/13.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import "CacheViewController.h"
-#import <KTVHTTPCache/KTVHTTPCache.h>
-#import "CacheItemZoneCell.h"
-#import "CacheItemView.h"
-
-@interface CacheViewController () <UITableViewDelegate, UITableViewDataSource, CacheItemViewDelegate>
-
-@property (weak, nonatomic) IBOutlet UITableView * tableView;
-@property (nonatomic, strong) NSArray <KTVHCDataCacheItem *> * cacheItems;
-
-@end
-
-@implementation CacheViewController
-
-- (void)viewDidLoad
-{
-    [super viewDidLoad];
-    
-    [self reloadData];
-}
-
-- (void)reloadData
-{
-    self.cacheItems = [KTVHTTPCache cacheAllCacheItems];
-    [self.tableView reloadData];
-}
-
-#pragma mark - Table View
-
-- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
-{
-    return self.cacheItems.count;
-}
-
-- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
-{
-    return [self.cacheItems objectAtIndex:section].zones.count;
-}
-
-- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
-{
-    KTVHCDataCacheItemZone * zone = [[self.cacheItems objectAtIndex:indexPath.section].zones objectAtIndex:indexPath.row];
-
-    CacheItemZoneCell * cell = [tableView dequeueReusableCellWithIdentifier:@"CacheItemZoneCell"];
-    [cell configureWithOffset:zone.offset length:zone.length];
-    
-    return cell;
-}
-
-- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
-{
-    KTVHCDataCacheItem * item = [self.cacheItems objectAtIndex:section];
-    CacheItemView * view = [[CacheItemView alloc] initWithURLString:item.URL.absoluteString
-                                                        totalLength:item.totalLength
-                                                        cacheLength:item.cacheLength];
-    view.delegate = self;
-    return view;
-}
-
-- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
-{
-    return 120;
-}
-
-#pragma mark - CacheItemViewDelegate
-
-- (void)cacheItemView:(CacheItemView *)view deleteButtonDidClick:(NSString *)URLString
-{
-    [KTVHTTPCache cacheDeleteCacheWithURLString:URLString];
-    [self reloadData];
-}
-
-- (IBAction)deleteAllCache:(UIButton *)sender
-{
-    [KTVHTTPCache cacheDeleteAllCaches];
-    [self reloadData];
-}
-
-@end

+ 0 - 43
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Info.plist

@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>CFBundleDevelopmentRegion</key>
-	<string>en</string>
-	<key>CFBundleExecutable</key>
-	<string>$(EXECUTABLE_NAME)</string>
-	<key>CFBundleIdentifier</key>
-	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
-	<key>CFBundleInfoDictionaryVersion</key>
-	<string>6.0</string>
-	<key>CFBundleName</key>
-	<string>$(PRODUCT_NAME)</string>
-	<key>CFBundlePackageType</key>
-	<string>APPL</string>
-	<key>CFBundleShortVersionString</key>
-	<string>1.0.0</string>
-	<key>CFBundleVersion</key>
-	<string>1</string>
-	<key>LSRequiresIPhoneOS</key>
-	<true/>
-	<key>NSAppTransportSecurity</key>
-	<dict>
-		<key>NSAllowsArbitraryLoads</key>
-		<true/>
-	</dict>
-	<key>UILaunchStoryboardName</key>
-	<string>LaunchScreen</string>
-	<key>UIMainStoryboardFile</key>
-	<string>Main</string>
-	<key>UIRequiredDeviceCapabilities</key>
-	<array>
-		<string>armv7</string>
-	</array>
-	<key>UISupportedInterfaceOrientations</key>
-	<array>
-		<string>UIInterfaceOrientationPortrait</string>
-		<string>UIInterfaceOrientationLandscapeLeft</string>
-		<string>UIInterfaceOrientationLandscapeRight</string>
-	</array>
-</dict>
-</plist>

+ 0 - 15
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Media/MediaCell.h

@@ -1,15 +0,0 @@
-//
-//  MediaCell.h
-//  KTVHTTPCacheDemo
-//
-//  Created by Single on 2017/8/13.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface MediaCell : UITableViewCell
-
-- (void)configureWithTitle:(NSString *)title;
-
-@end

+ 0 - 24
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Media/MediaCell.m

@@ -1,24 +0,0 @@
-//
-//  MediaCell.m
-//  KTVHTTPCacheDemo
-//
-//  Created by Single on 2017/8/13.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import "MediaCell.h"
-
-@interface MediaCell ()
-
-@property (weak, nonatomic) IBOutlet UILabel * titleLabel;
-
-@end
-
-@implementation MediaCell
-
-- (void)configureWithTitle:(NSString *)title
-{
-    self.titleLabel.text = title;
-}
-
-@end

+ 0 - 18
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Media/MediaItem.h

@@ -1,18 +0,0 @@
-//
-//  MediaItem.h
-//  KTVHTTPCacheDemo
-//
-//  Created by Single on 2017/8/13.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-@interface MediaItem : NSObject
-
-- (instancetype)initWithTitle:(NSString *)title URLString:(NSString *)URLString;
-
-@property (nonatomic, copy) NSString * title;
-@property (nonatomic, copy) NSString * URLString;
-
-@end

+ 0 - 23
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Media/MediaItem.m

@@ -1,23 +0,0 @@
-//
-//  MediaItem.m
-//  KTVHTTPCacheDemo
-//
-//  Created by Single on 2017/8/13.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import "MediaItem.h"
-
-@implementation MediaItem
-
-- (instancetype)initWithTitle:(NSString *)title URLString:(NSString *)URLString
-{
-    if (self = [super init])
-    {
-        self.title = title;
-        self.URLString = URLString;
-    }
-    return self;
-}
-
-@end

+ 0 - 15
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Media/MediaViewController.h

@@ -1,15 +0,0 @@
-//
-//  MediaViewController.h
-//  KTVHTTPCacheDemo
-//
-//  Created by Single on 2017/8/14.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <AVKit/AVKit.h>
-
-@interface MediaViewController : AVPlayerViewController
-
-- (instancetype)initWithURLString:(NSString *)URLString;
-
-@end

+ 0 - 44
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/Media/MediaViewController.m

@@ -1,44 +0,0 @@
-//
-//  MediaViewController.m
-//  KTVHTTPCacheDemo
-//
-//  Created by Single on 2017/8/14.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import "MediaViewController.h"
-#import <AVFoundation/AVFoundation.h>
-
-@interface MediaViewController ()
-
-@property (nonatomic, strong) NSString * URLString;
-
-@end
-
-@implementation MediaViewController
-
-- (instancetype)initWithURLString:(NSString *)URLString
-{
-    if (self = [super init])
-    {
-        self.URLString = URLString;
-    }
-    return self;
-}
-
-- (void)viewDidLoad
-{
-    [super viewDidLoad];
-    
-    self.player = [AVPlayer playerWithURL:[NSURL URLWithString:self.URLString]];
-    [self.player play];
-}
-
-- (void)dealloc
-{
-    [self.player.currentItem.asset cancelLoading];
-    [self.player.currentItem cancelPendingSeeks];
-    [self.player cancelPendingPrerolls];
-}
-
-@end

+ 0 - 14
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/ViewController.h

@@ -1,14 +0,0 @@
-//
-//  ViewController.h
-//  KTVHTTPCacheDemo
-//
-//  Created by Single on 2017/8/10.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface ViewController : UIViewController
-
-@end
-

+ 0 - 97
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/ViewController.m

@@ -1,97 +0,0 @@
-//
-//  ViewController.m
-//  KTVHTTPCacheDemo
-//
-//  Created by Single on 2017/8/10.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import "ViewController.h"
-#import "MediaViewController.h"
-#import "MediaItem.h"
-#import "MediaCell.h"
-#import <KTVHTTPCache/KTVHTTPCache.h>
-
-@interface ViewController () <UITableViewDelegate, UITableViewDataSource>
-
-@property (weak, nonatomic) IBOutlet UITableView * tableView;
-@property (nonatomic, strong) NSArray <MediaItem *> * medaiItems;
-
-@end
-
-@implementation ViewController
-
-- (void)viewDidLoad
-{
-    [super viewDidLoad];
-    static dispatch_once_t onceToken;
-    dispatch_once(&onceToken, ^{
-        [self setupHTTPCache];
-    });
-    [self reloadData];
-}
-
-- (void)setupHTTPCache
-{
-    [KTVHTTPCache logSetConsoleLogEnable:YES];
-    NSError * error;
-    [KTVHTTPCache proxyStart:&error];
-    if (error) {
-        NSLog(@"Proxy Start Failure, %@", error);
-    } else {
-        NSLog(@"Proxy Start Success");
-    }
-    [KTVHTTPCache tokenSetURLFilter:^NSURL * (NSURL * URL) {
-        NSLog(@"URL Filter reviced URL : %@", URL);
-        return URL;
-    }];
-    [KTVHTTPCache downloadSetUnsupportContentTypeFilter:^BOOL(NSURL * URL, NSString * contentType) {
-        NSLog(@"Unsupport Content-Type Filter reviced URL : %@, %@", URL, contentType);
-        return NO;
-    }];
-}
-
-- (void)reloadData
-{
-    MediaItem * item1 = [[MediaItem alloc] initWithTitle:@"萧亚轩 - 冲动"
-                                               URLString:@"http://aliuwmp3.changba.com/userdata/video/45F6BD5E445E4C029C33DC5901307461.mp4"];
-    MediaItem * item2 = [[MediaItem alloc] initWithTitle:@"张惠妹 - 你是爱我的"
-                                               URLString:@"http://aliuwmp3.changba.com/userdata/video/3B1DDE764577E0529C33DC5901307461.mp4"];
-    MediaItem * item3 = [[MediaItem alloc] initWithTitle:@"hush! - 都是你害的"
-                                               URLString:@"http://qiniuuwmp3.changba.com/941946870.mp4"];
-    MediaItem * item4 = [[MediaItem alloc] initWithTitle:@"张学友 - 我真的受伤了"
-                                               URLString:@"http://lzaiuw.changba.com/userdata/video/940071102.mp4"];
-    self.medaiItems = @[item1, item2, item3, item4];
-    [self.tableView reloadData];
-}
-
-- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
-{
-    return 1;
-}
-
-- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
-{
-    return self.medaiItems.count;
-}
-
-- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
-{
-    MediaCell * cell = [tableView dequeueReusableCellWithIdentifier:@"MediaCell"];
-    [cell configureWithTitle:[self.medaiItems objectAtIndex:indexPath.row].title];
-    return cell;
-}
-
-- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
-{
-    MediaItem * mediaItem = [self.medaiItems objectAtIndex:indexPath.row];
-    NSString * URLString = [mediaItem.URLString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
-
-    NSString * proxyURLString = [KTVHTTPCache proxyURLStringWithOriginalURLString:URLString];
-    
-    MediaViewController * viewController = [[MediaViewController alloc] initWithURLString:proxyURLString];
-    [self presentViewController:viewController animated:YES completion:nil];
-}
-
-
-@end

+ 0 - 16
Carthage/Checkouts/KTVHTTPCache/demo/KTVHTTPCacheDemo/KTVHTTPCacheDemo/main.m

@@ -1,16 +0,0 @@
-//
-//  main.m
-//  KTVHTTPCacheDemo
-//
-//  Created by Single on 2017/8/10.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-#import "AppDelegate.h"
-
-int main(int argc, char * argv[]) {
-    @autoreleasepool {
-        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
-    }
-}

+ 4 - 4
Carthage/Checkouts/realm-cocoa/.jenkins.yml

@@ -7,7 +7,7 @@ xcode_version:
   - 9.4
   - 10.0
   - 10.1
-  - 10.2
+  - 10.2.1
 target:
   - osx
   - docs
@@ -56,8 +56,8 @@ configuration:
 # | 10.1  | Debug        | X   |      |            |             |           |           |         |               |               |                   |           |      |                |                   |                      |                       |                       |                        |             |
 # | 10.1  | Release      | X   |      | X          | X           | X         | X         | X       | X             | X             | X                 |           | X    |                |                   |                      |                       |                       |                        |             |
 # | -------------------- | --- | ---- | ---------- | ----------- | --------- | --------- | ------- | ------------- | ------------- | ----------------- | --------- | ---- | -------------- | ----------------- | -------------------- | --------------------- | --------------------- | ---------------------- | ----------- |
-# | 10.2  | Debug        | X   |      |            | X           | X         | X         | X       |               |               |                   |           | X    |                |                   |                      |                       |                       |                        |             |
-# | 10.2  | Release      | X   | X    | X          | X           | X         | X         | X       | X             | X             | X                 | X         | X    | X              | X                 |                      |                       | X                     |                        | X           |
+# | 10.2.1| Debug        | X   |      |            | X           | X         | X         | X       |               |               |                   |           | X    |                |                   |                      |                       |                       |                        |             |
+# | 10.2.1| Release      | X   | X    | X          | X           | X         | X         | X       | X             | X             | X                 | X         | X    | X              | X                 |                      |                       | X                     |                        | X           |
 # +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 
 exclude:
@@ -94,7 +94,7 @@ exclude:
   - xcode_version: 10.1
     target: ios-static
     configuration: Debug
-  - xcode_version: 10.2
+  - xcode_version: 10.2.1
     target: ios-static
     configuration: Debug
 

+ 1 - 1
Carthage/Checkouts/realm-cocoa/.travis.yml

@@ -1,5 +1,5 @@
 language: objective-c
-osx_image: xcode9.3
+osx_image: xcode10.2
 branches:
   only: master
 script: placeholder # workaround for https://github.com/travis-ci/travis-ci/issues/4681

+ 68 - 0
Carthage/Checkouts/realm-cocoa/CHANGELOG.md

@@ -1,3 +1,70 @@
+3.15.0 Release notes (2019-05-06)
+=============================================================
+
+The minimum version of Realm Object Server has been increased to 3.21.0 and
+attempting to connect to older versions will produce protocol mismatch errors.
+Realm Cloud has already been upgraded to this version, and users using that do
+not need to worry about this.
+
+### Enhancements
+
+* Add `createdAt`, `updatedAt`, `expiresAt` and `timeToLive` properties to
+  `RLMSyncSubscription`/`SyncSubscription`. These properties will be `nil` for
+  subscriptions created with older versions of Realm, but will be automatically
+  populated for newly-created subscriptions.
+* Add support for transient subscriptions by setting the `timeToLive` when
+  creating the subscription. The next time a subscription is created or updated
+  after that time has elapsed the subscription will be automatically removed.
+* Add support for updating existing subscriptions with a new query or limit.
+  This is done by passing `update: true` (in swift) or setting
+  `options.overwriteExisting = YES` (in obj-c) when creating the subscription,
+  which will make it update the existing subscription with the same name rather
+  than failing if one already exists with that name.
+* Add an option to include the objects from
+  `RLMLinkingObjects`/`LinkingObjects` properties in sync subscriptions,
+  similarly to how `RLMArray`/`List` automatically pull in the contained
+  objects.
+* Improve query performance for chains of OR conditions (or an IN condition) on
+  an unindexed integer or string property.
+  ([Core PR #2888](https://github.com/realm/realm-core/pull/2888) and
+  [Core PR #3250](https://github.com/realm/realm-core/pull/3250)).
+* Improve query performance for equality conditions on indexed integer properties.
+  ([Core PR #3272](https://github.com/realm/realm-core/pull/3272)).
+* Adjust the file allocation algorithm to reduce fragmentation caused by large
+  numbers of small blocks.
+* Improve file allocator logic to reduce fragmentation and improve commit
+  performance after many writes. ([Core PR #3278](https://github.com/realm/realm-core/pull/3278)).
+
+### Fixed
+
+* Making a query that compares two integer properties could cause a
+  segmentation fault on x86 (i.e. macOS only).
+  ([Core PR #3253](https://github.com/realm/realm-core/pull/3256)).
+* The `downloadable_bytes` parameter passed to sync progress callbacks reported
+  a value which correlated to the amount of data left to download, but not
+  actually the number of bytes which would be downloaded.
+
+### Compatibility
+
+* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)
+* Realm Object Server: 3.21.0 or later.
+* Carthage release for Swift is built with Xcode 10.2.1.
+
+3.14.2 Release notes (2019-04-25)
+=============================================================
+
+### Enhancements
+
+* Updating `RLMSyncManager.customRequestHeaders` will immediately update all
+  currently active sync session with the new headers rather than requiring
+  manually closing the Realm and reopening it.
+
+### Compatibility
+
+* File format: Generates Realms with format v9 (Reads and upgrades all previous formats)
+* Realm Object Server: 3.11.0 or later.
+* Carthage release for Swift is built with Xcode 10.2.1.
+
 3.14.1 Release notes (2019-04-04)
 =============================================================
 
@@ -11,6 +78,7 @@
 
 * File format: Generates Realms with format v9 (Reads and upgrades all previous formats)
 * Realm Object Server: 3.11.0 or later.
+* Carthage release for Swift is built with Xcode 10.2.
 
 3.14.0 Release notes (2019-03-27)
 =============================================================

+ 3 - 3
Carthage/Checkouts/realm-cocoa/Jenkinsfile.releasability

@@ -1,8 +1,8 @@
-xcodeVersions = ['9.2', '9.3', '9.4', '10.0', '10.1', '10.2']
+xcodeVersions = ['9.2', '9.3', '9.4', '10.0', '10.1', '10.2.1']
 platforms = ['osx', 'ios', 'watchos', 'tvos']
 platformNames = ['osx': 'macOS', 'ios': 'iOS', 'watchos': 'watchOS', 'tvos': 'tvOS']
-carthageXcodeVersion = '10.2'
-docsSwiftVersion = '5.0'
+carthageXcodeVersion = '10.2.1'
+docsSwiftVersion = '5.0.1'
 
 def installationTest(platform, test, language) {
   return {

+ 155 - 31
Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/RLMObjectServerTests.mm

@@ -20,11 +20,14 @@
 #import "RLMTestUtils.h"
 #import "RLMSyncSessionRefreshHandle+ObjectServerTests.h"
 #import "RLMSyncUser+ObjectServerTests.h"
-#import "RLMSyncUtil_Private.h"
+
 #import "RLMRealm+Sync.h"
 #import "RLMRealmConfiguration_Private.h"
 #import "RLMRealmUtil.hpp"
 #import "RLMRealm_Dynamic.h"
+#import "RLMRealm_Private.hpp"
+#import "RLMSyncUtil_Private.h"
+#import "shared_realm.hpp"
 
 #pragma mark - Test objects
 
@@ -1446,7 +1449,6 @@
     __block NSInteger callCount = 0;
     __block NSUInteger transferred = 0;
     __block NSUInteger transferrable = 0;
-    __block BOOL hasBeenFulfilled = NO;
     // Open the Realm
     RLMRealm *realm = [self openRealmForURL:url user:user];
 
@@ -1454,24 +1456,21 @@
     RLMSyncSession *session = [user sessionForURL:url];
     XCTAssertNotNil(session);
     XCTestExpectation *ex = [self expectationWithDescription:@"streaming-upload-expectation"];
-    RLMProgressNotificationToken *token = [session addProgressNotificationForDirection:RLMSyncProgressDirectionUpload
-                                                                                  mode:RLMSyncProgressModeReportIndefinitely
-                                                                                 block:^(NSUInteger xfr, NSUInteger xfb) {
-                                                                                     // Make sure the values are
-                                                                                     // increasing, and update our
-                                                                                     // stored copies.
-                                                                                     XCTAssert(xfr >= transferred);
-                                                                                     XCTAssert(xfb >= transferrable);
-                                                                                     transferred = xfr;
-                                                                                     transferrable = xfb;
-                                                                                     callCount++;
-                                                                                     if (transferred > 0
-                                                                                         && transferred >= transferrable
-                                                                                         && !hasBeenFulfilled) {
-                                                                                         [ex fulfill];
-                                                                                         hasBeenFulfilled = YES;
-                                                                                     }
-                                                                                 }];
+    auto token = [session addProgressNotificationForDirection:RLMSyncProgressDirectionUpload
+                                                         mode:RLMSyncProgressModeReportIndefinitely
+                                                        block:^(NSUInteger xfr, NSUInteger xfb) {
+                                                            // Make sure the values are
+                                                            // increasing, and update our
+                                                            // stored copies.
+                                                            XCTAssert(xfr >= transferred);
+                                                            XCTAssert(xfb >= transferrable);
+                                                            transferred = xfr;
+                                                            transferrable = xfb;
+                                                            callCount++;
+                                                            if (transferred > 0 && transferred >= transferrable && transferrable > 1000000 * NUMBER_OF_BIG_OBJECTS) {
+                                                                [ex fulfill];
+                                                            }
+                                                        }];
     // Upload lots of data
     [realm beginWriteTransaction];
     for (NSInteger i=0; i<NUMBER_OF_BIG_OBJECTS; i++) {
@@ -1555,21 +1554,16 @@
         return;
     }
 
-    // Wait for the child process to upload everything.
-    RLMRunChildAndWait();
-
     XCTestExpectation *ex = [self expectationWithDescription:@"download-realm"];
     RLMRealmConfiguration *c = [user configurationWithURL:url fullSynchronization:true];
     XCTAssertFalse([[NSFileManager defaultManager] fileExistsAtPath:c.pathOnDisk isDirectory:nil]);
     RLMRealm *realm = [RLMRealm realmWithConfiguration:c error:nil];
     CHECK_COUNT(0, HugeSyncObject, realm);
-    [RLMRealm asyncOpenWithConfiguration:c
-                           callbackQueue:dispatch_get_main_queue()
-                                callback:^(RLMRealm * _Nullable realm, NSError * _Nullable error) {
-        XCTAssertNil(error);
-        CHECK_COUNT(NUMBER_OF_BIG_OBJECTS, HugeSyncObject, realm);
-        [ex fulfill];
-    }];
+    [realm.syncSession suspend];
+
+    // Wait for the child process to upload everything.
+    RLMRunChildAndWait();
+
     auto fileSize = ^NSUInteger(NSString *path) {
         NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
         return [(NSNumber *)attributes[NSFileSize] unsignedLongLongValue];
@@ -1577,11 +1571,22 @@
     NSUInteger sizeBefore = fileSize(c.pathOnDisk);
     XCTAssertGreaterThan(sizeBefore, 0U);
     XCTAssertNotNil(RLMGetAnyCachedRealmForPath(c.pathOnDisk.UTF8String));
+
+    [RLMRealm asyncOpenWithConfiguration:c
+                           callbackQueue:dispatch_get_main_queue()
+                                callback:^(RLMRealm * _Nullable realm, NSError * _Nullable error) {
+        XCTAssertNil(error);
+        CHECK_COUNT(NUMBER_OF_BIG_OBJECTS, HugeSyncObject, realm);
+        [ex fulfill];
+    }];
+    [realm.syncSession resume];
     [self waitForExpectationsWithTimeout:2.0 handler:nil];
 
     XCTAssertGreaterThan(fileSize(c.pathOnDisk), sizeBefore);
     XCTAssertNotNil(RLMGetAnyCachedRealmForPath(c.pathOnDisk.UTF8String));
     CHECK_COUNT(NUMBER_OF_BIG_OBJECTS, HugeSyncObject, realm);
+
+    (void)[realm configuration];
 }
 
 - (void)testDownloadCancelsOnAuthError {
@@ -1645,7 +1650,9 @@
 
     auto finalSize = [[fileManager attributesOfItemAtPath:path error:nil][NSFileSize] unsignedLongLongValue];
     XCTAssertLessThan(finalSize, initialSize);
-    XCTAssertLessThan(finalSize, 10000U);
+    // Immediately after compaction the file is two pages (8192 bytes), but it
+    // grows to three pages shortly later due to sync performing a write
+    XCTAssertLessThanOrEqual(finalSize, 12288U);
 }
 
 #pragma mark - Offline Client Reset
@@ -1889,6 +1896,11 @@
     [self waitForKeyPath:@"state" object:fetched value:@(RLMSyncSubscriptionStateInvalidated)];
     XCTAssertEqual(0U, realm.subscriptions.count);
     XCTAssertEqual(RLMSyncSubscriptionStateInvalidated, original.state);
+
+    // XCTKVOExpecatation retains the object and releases it sometime later on
+    // a background thread, which causes issues if the realm is closed after
+    // we reset the global state
+    realm->_realm->close();
 }
 
 - (void)testUnsubscribeUsingFetchedSubscriptionObservingFetched {
@@ -1902,6 +1914,11 @@
     [self waitForKeyPath:@"state" object:fetched value:@(RLMSyncSubscriptionStateInvalidated)];
     XCTAssertEqual(0U, realm.subscriptions.count);
     XCTAssertEqual(RLMSyncSubscriptionStateInvalidated, original.state);
+
+    // XCTKVOExpecatation retains the object and releases it sometime later on
+    // a background thread, which causes issues if the realm is closed after
+    // we reset the global state
+    realm->_realm->close();
 }
 
 - (void)testUnsubscribeUsingFetchedSubscriptionObservingOriginal {
@@ -1944,6 +1961,7 @@
 - (void)testSortAndFilterSubscriptions {
     RLMRealm *realm = [self partialRealmWithName:_cmd];
 
+    NSDate *now = NSDate.date;
     [self waitForKeyPath:@"state" object:[[PartialSyncObjectA allObjectsInRealm:realm] subscribeWithName:@"query 1"]
                    value:@(RLMSyncSubscriptionStateComplete)];
     [self waitForKeyPath:@"state" object:[[PartialSyncObjectA allObjectsInRealm:realm] subscribeWithName:@"query 2"]
@@ -1961,11 +1979,47 @@
     XCTAssertEqual(3U, ([subscriptions objectsWhere:@"status = %@", @(RLMSyncSubscriptionStateComplete)].count));
     XCTAssertEqual(1U, ([subscriptions objectsWhere:@"status = %@", @(RLMSyncSubscriptionStateError)].count));
 
+    XCTAssertEqual(4U, ([subscriptions objectsWhere:@"createdAt >= %@", now]).count);
+    XCTAssertEqual(0U, ([subscriptions objectsWhere:@"createdAt < %@", now]).count);
+    XCTAssertEqual(4U, [subscriptions objectsWhere:@"expiresAt = nil"].count);
+    XCTAssertEqual(4U, [subscriptions objectsWhere:@"timeToLive = nil"].count);
+
     XCTAssertThrows([subscriptions sortedResultsUsingKeyPath:@"name" ascending:NO]);
     XCTAssertThrows([subscriptions sortedResultsUsingDescriptors:@[]]);
     XCTAssertThrows([subscriptions distinctResultsUsingKeyPaths:@[@"name"]]);
 }
 
+- (void)testIncludeLinkingObjectsErrorHandling {
+    RLMRealm *realm = [self partialRealmWithName:_cmd];
+
+    RLMResults *objects = [PersonObject allObjectsInRealm:realm];
+    RLMSyncSubscriptionOptions *opt = [RLMSyncSubscriptionOptions new];
+
+    opt.includeLinkingObjectProperties = @[@"nonexistent"];
+    RLMAssertThrowsWithReason([objects subscribeWithOptions:opt],
+                              @"Invalid LinkingObjects inclusion from key path 'nonexistent': property 'PersonObject.nonexistent' does not exist.");
+
+    opt.includeLinkingObjectProperties = @[@"name"];
+    RLMAssertThrowsWithReason([objects subscribeWithOptions:opt],
+                              @"Invalid LinkingObjects inclusion from key path 'name': property 'PersonObject.name' is of unsupported type 'string'.");
+
+    opt.includeLinkingObjectProperties = @[@"children.name"];
+    RLMAssertThrowsWithReason([objects subscribeWithOptions:opt],
+                              @"Invalid LinkingObjects inclusion from key path 'children.name': property 'PersonObject.name' is of unsupported type 'string'.");
+
+    opt.includeLinkingObjectProperties = @[@"children"];
+    RLMAssertThrowsWithReason([objects subscribeWithOptions:opt],
+                              @"Invalid LinkingObjects inclusion from key path 'children': key path must end in a LinkingObjects property and 'PersonObject.children' is of type 'array'.");
+
+    opt.includeLinkingObjectProperties = @[@"children."];
+    RLMAssertThrowsWithReason([objects subscribeWithOptions:opt],
+                              @"Invalid LinkingObjects inclusion from key path 'children.': missing property name.");
+
+    opt.includeLinkingObjectProperties = @[@""];
+    RLMAssertThrowsWithReason([objects subscribeWithOptions:opt],
+                              @"Invalid LinkingObjects inclusion from key path '': missing property name.");
+}
+
 #pragma mark - Certificate pinning
 
 - (void)attemptLoginWithUsername:(NSString *)userName callback:(void (^)(RLMSyncUser *, NSError *))callback {
@@ -2136,4 +2190,74 @@ static NSURL *certificateURL(NSString *filename) {
     [self verifyOpenFails:[user configurationWithURL:[NSURL URLWithString:@"realms://localhost:9443/~/default"]]];
 }
 
+#pragma mark - Custom request headers
+
+- (void)testLoginFailsWithoutCustomHeader {
+    XCTestExpectation *expectation = [self expectationWithDescription:@"register user"];
+    [RLMSyncUser logInWithCredentials:[RLMSyncTestCase basicCredentialsWithName:NSStringFromSelector(_cmd)
+                                                                       register:YES]
+                        authServerURL:[NSURL URLWithString:@"http://127.0.0.1:9081"]
+                         onCompletion:^(RLMSyncUser *user, NSError *error) {
+                             XCTAssertNil(user);
+                             XCTAssertNotNil(error);
+                             XCTAssertEqualObjects(@400, error.userInfo[@"statusCode"]);
+                             [expectation fulfill];
+                         }];
+    [self waitForExpectationsWithTimeout:4.0 handler:nil];
+}
+
+- (void)testLoginUsesCustomHeader {
+    RLMSyncManager.sharedManager.customRequestHeaders = @{@"X-Allow-Connection": @"true"};
+    RLMSyncUser *user = [self logInUserForCredentials:[RLMSyncTestCase basicCredentialsWithName:NSStringFromSelector(_cmd)
+                                                                                       register:YES]
+                                               server:[NSURL URLWithString:@"http://127.0.0.1:9081"]];
+    XCTAssertNotNil(user);
+}
+
+- (void)testModifyCustomHeadersAfterOpeningRealm {
+    RLMSyncManager.sharedManager.customRequestHeaders = @{@"X-Allow-Connection": @"true"};
+    RLMSyncUser *user = [self logInUserForCredentials:[RLMSyncTestCase basicCredentialsWithName:NSStringFromSelector(_cmd)
+                                                                                       register:YES]
+                                               server:[NSURL URLWithString:@"http://127.0.0.1:9081"]];
+    XCTAssertNotNil(user);
+
+    RLMSyncManager.sharedManager.customRequestHeaders = nil;
+
+    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"realm://127.0.0.1:9081/~/%@", NSStringFromSelector(_cmd)]];
+    auto c = [user configurationWithURL:url fullSynchronization:true];
+
+    // Should initially fail to connect due to the missing header
+    XCTestExpectation *ex1 = [self expectationWithDescription:@"connection failure"];
+    RLMSyncManager.sharedManager.errorHandler = ^(NSError *error, RLMSyncSession *) {
+        XCTAssertNotNil(error);
+        XCTAssertEqualObjects(@400, [error.userInfo[@"underlying_error"] userInfo][@"statusCode"]);
+        [ex1 fulfill];
+    };
+    RLMRealm *realm = [RLMRealm realmWithConfiguration:c error:nil];
+    RLMSyncSession *syncSession = realm.syncSession;
+    [self waitForExpectationsWithTimeout:4.0 handler:nil];
+    XCTAssertEqual(syncSession.connectionState, RLMSyncConnectionStateDisconnected);
+
+    // Should successfully connect once the header is set
+    RLMSyncManager.sharedManager.errorHandler = nil;
+    auto ex2 = [[XCTKVOExpectation alloc] initWithKeyPath:@"connectionState"
+                                                   object:syncSession
+                                            expectedValue:@(RLMSyncConnectionStateConnected)];
+    RLMSyncManager.sharedManager.customRequestHeaders = @{@"X-Allow-Connection": @"true"};
+    [self waitForExpectations:@[ex2] timeout:4.0];
+
+    // Should disconnect and fail to reconnect when the wrong header is set
+    XCTestExpectation *ex3 = [self expectationWithDescription:@"reconnection failure"];
+    RLMSyncManager.sharedManager.errorHandler = ^(NSError *error, RLMSyncSession *) {
+        XCTAssertNotNil(error);
+        XCTAssertEqualObjects(@400, [error.userInfo[@"underlying_error"] userInfo][@"statusCode"]);
+        [ex3 fulfill];
+    };
+    auto ex4 = [[XCTKVOExpectation alloc] initWithKeyPath:@"connectionState"
+                                                   object:syncSession
+                                            expectedValue:@(RLMSyncConnectionStateDisconnected)];
+    RLMSyncManager.sharedManager.customRequestHeaders = @{@"X-Other-Header": @"true"};
+    [self waitForExpectations:@[ex3, ex4] timeout:4.0];
+}
+
 @end

+ 0 - 173
Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/SwiftObjectServerTests.swift

@@ -98,7 +98,6 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
         }
     }
 
-#if swift(>=3.2)
     func testConnectionState() {
         let user = try! synchronouslyLogInUser(for: basicCredentials(register: true), server: authURL)
         let realm = try! synchronouslyOpenRealm(url: realmURL, user: user)
@@ -124,7 +123,6 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
         wait(forState: .connecting)
         wait(forState: .connected)
     }
-#endif // Swift >= 3.2
 
     // MARK: - Client reset
 
@@ -430,177 +428,6 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
         }
     }
 
-    // MARK: - Partial sync
-
-    func populateTestRealm(_ username: String) {
-        autoreleasepool {
-            let credentials = SyncCredentials.usernamePassword(username: username, password: "a", register: true)
-            let user = try! synchronouslyLogInUser(for: credentials, server: authURL)
-            let realm = try! synchronouslyOpenRealm(configuration: user.configuration())
-
-            try! realm.write {
-                realm.add(SwiftPartialSyncObjectA(number: 0, string: "realm"))
-                realm.add(SwiftPartialSyncObjectA(number: 1, string: ""))
-                realm.add(SwiftPartialSyncObjectA(number: 2, string: ""))
-                realm.add(SwiftPartialSyncObjectA(number: 3, string: ""))
-                realm.add(SwiftPartialSyncObjectA(number: 4, string: "realm"))
-                realm.add(SwiftPartialSyncObjectA(number: 5, string: "sync"))
-                realm.add(SwiftPartialSyncObjectA(number: 6, string: "partial"))
-                realm.add(SwiftPartialSyncObjectA(number: 7, string: "partial"))
-                realm.add(SwiftPartialSyncObjectA(number: 8, string: "partial"))
-                realm.add(SwiftPartialSyncObjectA(number: 9, string: "partial"))
-                realm.add(SwiftPartialSyncObjectB(number: 0, firstString: "", secondString: ""))
-                realm.add(SwiftPartialSyncObjectB(number: 1, firstString: "", secondString: ""))
-                realm.add(SwiftPartialSyncObjectB(number: 2, firstString: "", secondString: ""))
-                realm.add(SwiftPartialSyncObjectB(number: 3, firstString: "", secondString: ""))
-                realm.add(SwiftPartialSyncObjectB(number: 4, firstString: "", secondString: ""))
-                realm.add(SwiftPartialSyncObjectB(number: 5, firstString: "", secondString: ""))
-                realm.add(SwiftPartialSyncObjectB(number: 6, firstString: "", secondString: ""))
-                realm.add(SwiftPartialSyncObjectB(number: 7, firstString: "", secondString: ""))
-                realm.add(SwiftPartialSyncObjectB(number: 8, firstString: "", secondString: ""))
-                realm.add(SwiftPartialSyncObjectB(number: 9, firstString: "", secondString: ""))
-            }
-            waitForUploads(for: realm)
-        }
-    }
-
-    func testPartialSync() {
-        populateTestRealm(#function)
-
-        let credentials = SyncCredentials.usernamePassword(username: #function, password: "a")
-        let user = try! synchronouslyLogInUser(for: credentials, server: authURL)
-        let realm = try! synchronouslyOpenRealm(configuration: user.configuration())
-
-        let results = realm.objects(SwiftPartialSyncObjectA.self).filter("number > 5")
-        let subscription = results.subscribe(named: "query")
-        XCTAssertEqual(subscription.state, .creating)
-        waitForState(subscription, .complete)
-
-        // Verify that we got what we're looking for
-        XCTAssertEqual(results.count, 4)
-        for object in results {
-            XCTAssertGreaterThan(object.number, 5)
-            XCTAssertEqual(object.string, "partial")
-        }
-
-        // And that we didn't get anything else.
-        XCTAssertEqual(realm.objects(SwiftPartialSyncObjectA.self).count, results.count)
-        XCTAssertTrue(realm.objects(SwiftPartialSyncObjectB.self).isEmpty)
-
-        // Re-subscribing to an existing named query may not report the query's state immediately,
-        // but it should report it eventually.
-        let subscription2 = realm.objects(SwiftPartialSyncObjectA.self).filter("number > 5").subscribe(named: "query")
-        waitForState(subscription2, .complete)
-
-        // Creating a subscription with the same name but different query should raise an error.
-        let subscription3 = realm.objects(SwiftPartialSyncObjectA.self).filter("number < 5").subscribe(named: "query")
-        waitForError(subscription3)
-
-        // Unsubscribing should move the subscription to the invalidated state.
-        subscription.unsubscribe()
-        waitForState(subscription, .invalidated)
-    }
-
-    func testPartialSyncLimit() {
-        populateTestRealm(#function)
-
-        let credentials = SyncCredentials.usernamePassword(username: #function, password: "a")
-        let user = try! synchronouslyLogInUser(for: credentials, server: authURL)
-        let realm = try! synchronouslyOpenRealm(configuration: user.configuration())
-
-        let results = realm.objects(SwiftPartialSyncObjectA.self).filter("number > 5")
-        waitForState(results.subscribe(named: "query", limit: 1), .complete)
-        XCTAssertEqual(results.count, 1)
-        XCTAssertEqual(realm.objects(SwiftPartialSyncObjectA.self).count, 1)
-        if let object = results.first {
-            XCTAssertGreaterThan(object.number, 5)
-            XCTAssertEqual(object.string, "partial")
-        }
-
-        let results2 = realm.objects(SwiftPartialSyncObjectA.self).sorted(byKeyPath: "number", ascending: false)
-        waitForState(results2.subscribe(named: "query2", limit: 2), .complete)
-        XCTAssertEqual(results2.count, 3)
-        XCTAssertEqual(realm.objects(SwiftPartialSyncObjectA.self).count, 3)
-        for object in results2 {
-            XCTAssertTrue(object.number == 6 || object.number >= 8,
-                          "\(object.number) == 6 || \(object.number) >= 8")
-            XCTAssertEqual(object.string, "partial")
-        }
-    }
-
-    func testPartialSyncSubscriptions() {
-        let credentials = SyncCredentials.usernamePassword(username: #function, password: "a", register: true)
-        let user = try! synchronouslyLogInUser(for: credentials, server: authURL)
-        let realm = try! synchronouslyOpenRealm(configuration: user.configuration())
-
-        XCTAssertEqual(realm.subscriptions().count, 0)
-        XCTAssertNil(realm.subscription(named: "query"))
-
-        let subscription = realm.objects(SwiftPartialSyncObjectA.self).filter("number > 5").subscribe(named: "query")
-        XCTAssertEqual(realm.subscriptions().count, 0)
-        XCTAssertNil(realm.subscription(named: "query"))
-        waitForState(subscription, .complete)
-
-        XCTAssertEqual(realm.subscriptions().count, 1)
-        let sub2 = realm.subscriptions().first!
-        XCTAssertEqual(sub2.name, "query")
-        XCTAssertEqual(sub2.state, .complete)
-        let sub3 = realm.subscription(named: "query")!
-        XCTAssertEqual(sub3.name, "query")
-        XCTAssertEqual(sub3.state, .complete)
-        for sub in realm.subscriptions() {
-            XCTAssertEqual(sub.name, "query")
-            XCTAssertEqual(sub.state, .complete)
-        }
-
-        XCTAssertNil(realm.subscription(named: "not query"))
-    }
-
-// Partial sync subscriptions are only available in Swift 3.2 and newer.
-#if swift(>=3.2)
-    func waitForState<T>(_ subscription: SyncSubscription<T>, _ desiredState: SyncSubscriptionState) {
-        let ex = expectation(description: "Waiting for state \(desiredState)")
-        let token = subscription.observe(\.state, options: .initial) { state in
-            if state == desiredState {
-                ex.fulfill()
-            }
-        }
-        waitForExpectations(timeout: 20.0)
-        token.invalidate()
-    }
-
-    func waitForError<T>(_ subscription: SyncSubscription<T>) {
-        let ex = expectation(description: "Waiting for error state")
-        let token = subscription.observe(\.state, options: .initial) { state in
-            if case .error(_) = state {
-                ex.fulfill()
-            }
-        }
-        waitForExpectations(timeout: 20.0)
-        token.invalidate()
-    }
-#else
-    func waitForState<T>(_ subscription: SyncSubscription<T>, _ desiredState: SyncSubscriptionState) {
-        for _ in 0..<20 {
-            if subscription.state == desiredState {
-                return
-            }
-            RunLoop.current.run(until: Date().addingTimeInterval(1.0))
-        }
-        XCTFail("waitForState(\(subscription), \(desiredState)) timed out")
-    }
-
-    func waitForError<T>(_ subscription: SyncSubscription<T>) {
-        for _ in 0..<20 {
-            if case .error(_) = subscription.state {
-                return
-            }
-            RunLoop.current.run(until: Date().addingTimeInterval(1.0))
-        }
-        XCTFail("waitForError(\(subscription)) timed out")
-    }
-#endif // Swift >= 3.2
-
     // MARK: - Certificate Pinning
 
     func testSecureConnectionToLocalhostWithDefaultSecurity() {

+ 41 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectServerTests/test-ros-server.js

@@ -1,5 +1,7 @@
 const ROS = require('realm-object-server');
 const fs = require('fs');
+const http = require('http');
+const httpProxy = require('http-proxy');
 const os = require('os');
 const path = require('path');
 
@@ -46,6 +48,44 @@ class PasswordEmailHandler {
     }
 }
 
+// A simple proxy server that runs in front of ROS and validates custom headers
+class HeaderValidationProxy {
+    constructor(listenPort, targetPort) {
+        this.proxy = httpProxy.createProxyServer({target: `http://127.0.0.1:${targetPort}`, ws: true});
+        this.proxy.on('error', e => {
+            console.log('proxy error', e);
+        });
+        this.server = http.createServer((req, res) => {
+            if (this.validate(req)) {
+                this.proxy.web(req, res);
+            }
+            else {
+                res.writeHead(400);
+                res.end('Missing X-Allow-Connection header');
+            }
+        });
+        this.server.on('upgrade', (req, socket, head) => {
+            if (this.validate(req)) {
+                this.proxy.ws(req, socket, head);
+            }
+            else {
+                socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
+            }
+        });
+        this.server.listen(listenPort);
+    }
+
+    stop() {
+        this.server.close();
+        this.proxy.close();
+    }
+
+    validate(req) {
+        return !!req.headers['x-allow-connection'];
+    }
+}
+
+
 const server = new ROS.BasicServer();
 server.start({
     // The desired logging threshold. Can be one of: all, trace, debug, detail, info, warn, error, fatal, off)
@@ -78,3 +118,4 @@ server.start({
 }).catch(err => {
     console.error(`Error starting Realm Object Server: ${err.message}`)
 });
+new HeaderValidationProxy(9081, 9080);

+ 2 - 2
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/dependencies.list

@@ -1,4 +1,4 @@
-REALM_CORE_VERSION=5.12.7
-REALM_SYNC_VERSION=3.14.12
+REALM_CORE_VERSION=5.19.1
+REALM_SYNC_VERSION=4.4.2
 ANDROID_OPENSSL_VERSION=1.0.2k
 REALM_CORE_PACKAGING=2

+ 1 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/CMakeLists.txt

@@ -28,6 +28,7 @@ set(HEADERS
     execution_context_id.hpp
     feature_checks.hpp
     index_set.hpp
+    keypath_helpers.hpp
     list.hpp
     object.hpp
     object_accessor.hpp

+ 86 - 40
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/impl/realm_coordinator.cpp

@@ -76,7 +76,7 @@ std::shared_ptr<RealmCoordinator> RealmCoordinator::get_existing_coordinator(Str
     return it == s_coordinators_per_path.end() ? nullptr : it->second.lock();
 }
 
-void RealmCoordinator::create_sync_session()
+void RealmCoordinator::create_sync_session(bool force_client_reset)
 {
 #if REALM_ENABLE_SYNC
     if (m_sync_session)
@@ -94,7 +94,7 @@ void RealmCoordinator::create_sync_session()
 
     auto sync_config = *m_config.sync_config;
     sync_config.validate_sync_history = false;
-    m_sync_session = SyncManager::shared().get_session(m_config.path, sync_config);
+    m_sync_session = SyncManager::shared().get_session(m_config.path, sync_config, force_client_reset);
 
     std::weak_ptr<RealmCoordinator> weak_self = shared_from_this();
     SyncSession::Internal::set_sync_transact_callback(*m_sync_session,
@@ -106,6 +106,8 @@ void RealmCoordinator::create_sync_session()
                 self->m_notifier->notify_others();
         }
     });
+#else
+    static_cast<void>(force_client_reset);
 #endif
 }
 
@@ -183,6 +185,34 @@ void RealmCoordinator::set_config(const Realm::Config& config)
     }
 }
 
+std::shared_ptr<Realm> RealmCoordinator::get_cached_realm(Realm::Config const& config)
+{
+    if (!config.cache)
+        return nullptr;
+    AnyExecutionContextID execution_context(config.execution_context);
+    for (auto& cached_realm : m_weak_realm_notifiers) {
+        if (!cached_realm.is_cached_for_execution_context(execution_context))
+            continue;
+        // can be null if we jumped in between ref count hitting zero and
+        // unregister_realm() getting the lock
+        if (auto realm = cached_realm.realm()) {
+            // If the file is uninitialized and was opened without a schema,
+            // do the normal schema init
+            if (realm->schema_version() == ObjectStore::NotVersioned)
+                break;
+
+            // Otherwise if we have a realm schema it needs to be an exact
+            // match (even having the same properties but in different
+            // orders isn't good enough)
+            if (config.schema && realm->schema() != *config.schema)
+                throw MismatchedConfigException("Realm at path '%1' already opened on current thread with different schema.", config.path);
+
+            return realm;
+        }
+    }
+    return nullptr;
+}
+
 std::shared_ptr<Realm> RealmCoordinator::get_realm(Realm::Config config)
 {
     // realm must be declared before lock so that the mutex is released before
@@ -190,8 +220,16 @@ std::shared_ptr<Realm> RealmCoordinator::get_realm(Realm::Config config)
     // to acquire the same lock
     std::shared_ptr<Realm> realm;
     std::unique_lock<std::mutex> lock(m_realm_mutex);
+    do_get_realm(std::move(config), realm, lock);
+    return realm;
+}
 
+void RealmCoordinator::do_get_realm(Realm::Config config, std::shared_ptr<Realm>& realm,
+                                    std::unique_lock<std::mutex>& realm_lock)
+{
     set_config(config);
+    if ((realm = get_cached_realm(config)))
+        return;
 
     auto schema = std::move(config.schema);
     auto migration_function = std::move(config.migration_function);
@@ -199,57 +237,65 @@ std::shared_ptr<Realm> RealmCoordinator::get_realm(Realm::Config config)
     auto audit_factory = std::move(config.audit_factory);
     config.schema = {};
 
-    if (config.cache) {
-        AnyExecutionContextID execution_context(config.execution_context);
-        for (auto& cached_realm : m_weak_realm_notifiers) {
-            if (!cached_realm.is_cached_for_execution_context(execution_context))
-                continue;
-            // can be null if we jumped in between ref count hitting zero and
-            // unregister_realm() getting the lock
-            if ((realm = cached_realm.realm())) {
-                // If the file is uninitialized and was opened without a schema,
-                // do the normal schema init
-                if (realm->schema_version() == ObjectStore::NotVersioned)
-                    break;
-
-                // Otherwise if we have a realm schema it needs to be an exact
-                // match (even having the same properties but in different
-                // orders isn't good enough)
-                if (schema && realm->schema() != *schema)
-                    throw MismatchedConfigException("Realm at path '%1' already opened on current thread with different schema.", config.path);
-
-                return realm;
-            }
+    bool should_initialize_notifier = !config.immutable() && config.automatic_change_notifications;
+    realm = Realm::make_shared_realm(std::move(config), shared_from_this());
+    if (!m_notifier && should_initialize_notifier) {
+        try {
+            m_notifier = std::make_unique<ExternalCommitHelper>(*this);
         }
-    }
-
-    if (!realm) {
-        bool should_initialize_notifier = !config.immutable() && config.automatic_change_notifications;
-        realm = Realm::make_shared_realm(std::move(config), shared_from_this());
-        if (!m_notifier && should_initialize_notifier) {
-            try {
-                m_notifier = std::make_unique<ExternalCommitHelper>(*this);
-            }
-            catch (std::system_error const& ex) {
-                throw RealmFileException(RealmFileException::Kind::AccessError, get_path(), ex.code().message(), "");
-            }
+        catch (std::system_error const& ex) {
+            throw RealmFileException(RealmFileException::Kind::AccessError, get_path(), ex.code().message(), "");
         }
-        m_weak_realm_notifiers.emplace_back(realm, realm->config().cache);
     }
+    m_weak_realm_notifiers.emplace_back(realm, realm->config().cache);
 
     if (realm->config().sync_config)
-        create_sync_session();
+        create_sync_session(false);
 
     if (!m_audit_context && audit_factory)
         m_audit_context = audit_factory();
 
     if (schema) {
-        lock.unlock();
+        realm_lock.unlock();
         realm->update_schema(std::move(*schema), config.schema_version, std::move(migration_function),
                              std::move(initialization_function));
     }
+}
 
-    return realm;
+void RealmCoordinator::get_realm(Realm::Config config,
+                                 std::function<void(std::shared_ptr<Realm>, std::exception_ptr)> callback)
+{
+#if REALM_ENABLE_SYNC
+    if (config.sync_config) {
+        std::unique_lock<std::mutex> lock(m_realm_mutex);
+        set_config(config);
+        create_sync_session(!File::exists(m_config.path));
+        m_sync_session->wait_for_download_completion([callback, self = shared_from_this()](std::error_code ec) {
+            if (ec)
+                callback(nullptr, std::make_exception_ptr(std::system_error(ec)));
+            else {
+                std::shared_ptr<Realm> realm;
+                try {
+                    realm = self->get_realm();
+                }
+                catch (...) {
+                    return callback(nullptr, std::current_exception());
+                }
+                callback(realm, nullptr);
+            }
+        });
+        return;
+    }
+#endif
+
+    std::shared_ptr<Realm> realm;
+    try {
+        realm = get_realm(std::move(config));
+    }
+    catch (...) {
+        return callback(nullptr, std::current_exception());
+    }
+    callback(realm, nullptr);
 }
 
 std::shared_ptr<Realm> RealmCoordinator::get_realm()
@@ -925,7 +971,7 @@ void RealmCoordinator::process_available_async(Realm& realm)
 
 void RealmCoordinator::set_transaction_callback(std::function<void(VersionID, VersionID)> fn)
 {
-    create_sync_session();
+    create_sync_session(false);
     m_transaction_callback = std::move(fn);
 }
 

+ 5 - 1
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/impl/realm_coordinator.hpp

@@ -58,6 +58,7 @@ public:
     // configuration is compatible with the existing one
     std::shared_ptr<Realm> get_realm(Realm::Config config);
     std::shared_ptr<Realm> get_realm();
+    void get_realm(Realm::Config config, std::function<void(std::shared_ptr<Realm>, std::exception_ptr)> callback);
 
     Realm::Config get_config() const { return m_config; }
 
@@ -192,7 +193,10 @@ private:
     void pin_version(VersionID version);
 
     void set_config(const Realm::Config&);
-    void create_sync_session();
+    void create_sync_session(bool force_client_reset);
+    void do_get_realm(Realm::Config config, std::shared_ptr<Realm>& realm,
+                      std::unique_lock<std::mutex>& realm_lock);
+    std::shared_ptr<Realm> get_cached_realm(Realm::Config const& config);
 
     void run_async_notifiers();
     void open_helper_shared_group();

+ 3 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/object.hpp

@@ -70,6 +70,9 @@ public:
     template<typename ValueType, typename ContextType>
     ValueType get_property_value(ContextType& ctx, StringData prop_name);
 
+    template<typename ValueType, typename ContextType>
+    ValueType get_property_value(ContextType& ctx, const Property& property);
+
     // create an Object from a native representation
     template<typename ValueType, typename ContextType>
     static Object create(ContextType& ctx, std::shared_ptr<Realm> const& realm,

+ 6 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/object_accessor.hpp

@@ -56,6 +56,12 @@ void Object::set_property_value(ContextType& ctx, StringData prop_name, ValueTyp
     set_property_value_impl(ctx, property, value, try_update, false, false);
 }
 
+template <typename ValueType, typename ContextType>
+ValueType Object::get_property_value(ContextType& ctx, const Property& property)
+{
+    return get_property_value_impl<ValueType>(ctx, property);
+}
+
 template <typename ValueType, typename ContextType>
 ValueType Object::get_property_value(ContextType& ctx, StringData prop_name)
 {

+ 85 - 3
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/object_schema.cpp

@@ -93,7 +93,8 @@ ObjectSchema::ObjectSchema(Group const& group, StringData name, size_t index) :
     set_primary_key_property();
 }
 
-Property *ObjectSchema::property_for_name(StringData name) {
+Property *ObjectSchema::property_for_name(StringData name)
+{
     for (auto& prop : persisted_properties) {
         if (StringData(prop.name) == name) {
             return &prop;
@@ -107,11 +108,36 @@ Property *ObjectSchema::property_for_name(StringData name) {
     return nullptr;
 }
 
-const Property *ObjectSchema::property_for_name(StringData name) const {
+Property *ObjectSchema::property_for_public_name(StringData public_name)
+{
+    // If no `public_name` is defined, the internal `name` is also considered the public name.
+    for (auto& prop : persisted_properties) {
+        if (prop.public_name == public_name || (prop.public_name.empty() && prop.name == public_name))
+            return &prop;
+    }
+
+    // Computed properties are not persisted, so creating a public name for such properties
+    // are a bit pointless since the internal name is already the "public name", but since
+    // this distinction isn't visible in the Property struct we allow it anyway.
+    for (auto& prop : computed_properties) {
+        if ((prop.public_name.empty() ? StringData(prop.name) :  StringData(prop.public_name)) == public_name)
+            return &prop;
+    }
+    return nullptr;
+}
+
+const Property *ObjectSchema::property_for_public_name(StringData public_name) const
+{
+    return const_cast<ObjectSchema *>(this)->property_for_public_name(public_name);
+}
+
+const Property *ObjectSchema::property_for_name(StringData name) const
+{
     return const_cast<ObjectSchema *>(this)->property_for_name(name);
 }
 
-bool ObjectSchema::property_is_computed(Property const& property) const {
+bool ObjectSchema::property_is_computed(Property const& property) const
+{
     auto end = computed_properties.end();
     return std::find(computed_properties.begin(), end, property) != end;
 }
@@ -214,6 +240,62 @@ static void validate_property(Schema const& schema,
 
 void ObjectSchema::validate(Schema const& schema, std::vector<ObjectSchemaValidationException>& exceptions) const
 {
+    std::vector<StringData> public_property_names;
+    std::vector<StringData> internal_property_names;
+    internal_property_names.reserve(persisted_properties.size() + computed_properties.size());
+    auto gather_names = [&](auto const &properties) {
+        for (auto const &prop : properties) {
+            internal_property_names.push_back(prop.name);
+            if (!prop.public_name.empty())
+                public_property_names.push_back(prop.public_name);
+        }
+    };
+    gather_names(persisted_properties);
+    gather_names(computed_properties);
+    std::sort(public_property_names.begin(), public_property_names.end());
+    std::sort(internal_property_names.begin(), internal_property_names.end());
+
+    // Check that property names and aliases are unique
+    auto for_each_duplicate = [](auto &&container, auto &&fn) {
+        auto end = container.end();
+        for (auto it = std::adjacent_find(container.begin(), end); it != end; it = std::adjacent_find(it + 2, end))
+            fn(*it);
+    };
+    for_each_duplicate(public_property_names, [&](auto public_property_name) {
+        exceptions.emplace_back("Alias '%1' appears more than once in the schema for type '%2'.",
+                                public_property_name, name);
+    });
+    for_each_duplicate(internal_property_names, [&](auto internal_name) {
+        exceptions.emplace_back("Property '%1' appears more than once in the schema for type '%2'.",
+                                internal_name, name);
+    });
+
+    // Check that no aliases conflict with property names
+    struct ErrorWriter {
+        ObjectSchema const &os;
+        std::vector<ObjectSchemaValidationException> &exceptions;
+
+        struct Proxy {
+            ObjectSchema const &os;
+            std::vector<ObjectSchemaValidationException> &exceptions;
+
+            Proxy &operator=(StringData name) {
+                exceptions.emplace_back(
+                        "Property '%1.%2' has an alias '%3' that conflicts with a property of the same name.",
+                        os.name, os.property_for_public_name(name)->name, name);
+                return *this;
+            }
+        };
+
+        Proxy operator*() { return Proxy{os, exceptions}; }
+        ErrorWriter &operator=(const ErrorWriter &) { return *this; }
+        ErrorWriter &operator++() { return *this; }
+        ErrorWriter &operator++(int) { return *this; }
+    } writer{*this, exceptions};
+    std::set_intersection(public_property_names.begin(), public_property_names.end(),
+                          internal_property_names.begin(), internal_property_names.end(), writer);
+
+    // Validate all properties
     const Property *primary = nullptr;
     for (auto const& prop : persisted_properties) {
         validate_property(schema, name, prop, &primary, exceptions);

+ 2 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/object_schema.hpp

@@ -49,6 +49,8 @@ public:
     std::vector<Property> computed_properties;
     std::string primary_key;
 
+    Property *property_for_public_name(StringData public_name);
+    const Property *property_for_public_name(StringData public_name) const;
     Property *property_for_name(StringData name);
     const Property *property_for_name(StringData name) const;
     Property *primary_key_property() {

+ 25 - 4
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/property.hpp

@@ -62,7 +62,24 @@ struct Property {
     using IsPrimary = util::TaggedBool<class IsPrimaryTag>;
     using IsIndexed = util::TaggedBool<class IsIndexedTag>;
 
+    // The internal column name used in the Realm file.
     std::string name;
+
+    // The public name used by the binding to represent the internal column name in the Realm file. Bindings can use
+    // this to expose a different name in the binding API, e.g. to map between different naming conventions.
+    //
+    // Public names are only ever user defined, they are not persisted on disk, so reading the schema from the file
+    // will leave this field empty. If `public_name` is empty, the internal and public name are considered to be the same.
+    //
+    // ObjectStore will ensure that no conflicts occur between persisted properties and the public name, so
+    // the public name is just as unique an identifier as the internal name in the file.
+    //
+    // In order to respect public names bindings should use `ObjectSchema::property_for_public_name()` in the schema
+    // and `Object::value_for_property()` in the Object accessor for reading fields defined by the public name.
+    //
+    // For queries, bindings should provide an appropriate `KeyPathMapping` definition. Bindings are responsible
+    // for creating this.
+    std::string public_name;
     PropertyType type = PropertyType::Int;
     std::string object_type;
     std::string link_origin_property_name;
@@ -73,10 +90,10 @@ struct Property {
 
     Property() = default;
 
-    Property(std::string name, PropertyType type, IsPrimary primary = false, IsIndexed indexed = false);
+    Property(std::string name, PropertyType type, IsPrimary primary = false, IsIndexed indexed = false, std::string public_name = "");
 
     Property(std::string name, PropertyType type, std::string object_type,
-             std::string link_origin_property_name = "");
+             std::string link_origin_property_name = "", std::string public_name = "");
 
     Property(Property const&) = default;
     Property(Property&&) = default;
@@ -196,8 +213,10 @@ static const char *string_for_property_type(PropertyType type)
 }
 
 inline Property::Property(std::string name, PropertyType type,
-                          IsPrimary primary, IsIndexed indexed)
+                          IsPrimary primary, IsIndexed indexed,
+                          std::string public_name)
 : name(std::move(name))
+, public_name(std::move(public_name))
 , type(type)
 , is_primary(primary)
 , is_indexed(indexed)
@@ -206,8 +225,10 @@ inline Property::Property(std::string name, PropertyType type,
 
 inline Property::Property(std::string name, PropertyType type,
                           std::string object_type,
-                          std::string link_origin_property_name)
+                          std::string link_origin_property_name,
+                          std::string public_name)
 : name(std::move(name))
+, public_name(std::move(public_name))
 , type(type)
 , object_type(std::move(object_type))
 , link_origin_property_name(std::move(link_origin_property_name))

+ 15 - 8
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/results.cpp

@@ -627,14 +627,21 @@ Results Results::apply_ordering(DescriptorOrdering&& ordering)
     DescriptorOrdering new_order = m_descriptor_ordering;
     for (size_t i = 0; i < ordering.size(); ++i) {
         auto desc = ordering[i];
-        if (auto sort = dynamic_cast<const SortDescriptor*>(desc))
-            new_order.append_sort(std::move(*sort));
-        else if (auto distinct = dynamic_cast<const DistinctDescriptor*>(desc))
-            new_order.append_distinct(std::move(*distinct));
-        else if (auto limit = dynamic_cast<const LimitDescriptor*>(desc))
-            new_order.append_limit(std::move(*limit));
-        else
-            REALM_COMPILER_HINT_UNREACHABLE();
+        DescriptorType desc_type = ordering.get_type(i);
+        switch (desc_type) {
+            case DescriptorType::Sort:
+                new_order.append_sort(std::move(*dynamic_cast<const SortDescriptor*>(desc)));
+                break;
+            case DescriptorType::Distinct:
+                new_order.append_distinct(std::move(*dynamic_cast<const DistinctDescriptor*>(desc)));
+                break;
+            case DescriptorType::Limit:
+                new_order.append_limit(std::move(*dynamic_cast<const LimitDescriptor*>(desc)));
+                break;
+            case DescriptorType::Include:
+                new_order.append_include(std::move(*dynamic_cast<const IncludeDescriptor*>(desc)));
+                break;
+        }
     }
     return Results(m_realm, get_query(), std::move(new_order));
 }

+ 6 - 3
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/results.hpp

@@ -345,10 +345,13 @@ void Results::set_property_value(ContextType& ctx, StringData prop_name, ValueTy
         throw ModifyPrimaryKeyException(m_object_schema->name, prop->name);
     }
 
-    // Update all objects in this ResultSets
-    size_t size = this->size();
+    // Update all objects in this ResultSets. Use snapshot to avoid correctness problems if the
+    // object is removed from the TableView after the property update as well as avoiding to
+    // re-evaluating the query too many times.
+    auto snapshot = this->snapshot();
+    size_t size = snapshot.size();
     for (size_t i = 0; i < size; ++i) {
-        Object obj(m_realm, *m_object_schema, get(i));
+        Object obj(m_realm, *m_object_schema, snapshot.get(i));
         obj.set_property_value_impl(ctx, *prop, value, true, false, false);
     }
 }

+ 1 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/schema.cpp

@@ -80,6 +80,7 @@ void Schema::validate() const
 {
     std::vector<ObjectSchemaValidationException> exceptions;
 
+    // As the types are added sorted by name, we can detect duplicates by just looking at the following element.
     auto find_next_duplicate = [&](const_iterator start) {
         return std::adjacent_find(start, cend(), [](ObjectSchema const& lft, ObjectSchema const& rgt) {
             return lft.name == rgt.name;

+ 9 - 2
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/shared_realm.cpp

@@ -182,8 +182,9 @@ void Realm::open_with_config(const Config& config,
             SharedGroupOptions options;
             options.durability = config.in_memory ? SharedGroupOptions::Durability::MemOnly :
                                                     SharedGroupOptions::Durability::Full;
-
-            options.temp_dir = util::normalize_dir(config.fifo_files_fallback_path);
+            if (!config.fifo_files_fallback_path.empty()) {
+                options.temp_dir = util::normalize_dir(config.fifo_files_fallback_path);
+            }
             options.encryption_key = config.encryption_key.data();
             options.allow_file_format_upgrade = !config.disable_format_upgrade &&
                                                 config.schema_mode != SchemaMode::ResetFile;
@@ -271,6 +272,12 @@ SharedRealm Realm::get_shared_realm(Config config)
     return coordinator->get_realm(std::move(config));
 }
 
+void Realm::get_shared_realm(Config config, std::function<void(SharedRealm, std::exception_ptr)> callback)
+{
+    auto coordinator = RealmCoordinator::get_coordinator(config.path);
+    coordinator->get_realm(std::move(config), callback);
+}
+
 void Realm::set_schema(Schema const& reference, Schema schema)
 {
     m_dynamic_schema = false;

+ 10 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/src/shared_realm.hpp

@@ -261,6 +261,16 @@ public:
     // encryption key will raise an exception.
     static SharedRealm get_shared_realm(Config config);
 
+    // Open a Realm and then pass it to the callback.
+    //
+    // If SyncConfig is set, the callback will not be invoked until the latest
+    // Realm state has been fully downloaded. This will result in the callback
+    // being invoked on a different thread. The calling code should normally
+    // dispatch back to the desired thread and obtain a new reference to the
+    // Realm, only using the reference passed to the callback to keep the file
+    // open while this is happening.
+    static void get_shared_realm(Config config, std::function<void(SharedRealm, std::exception_ptr)> callback);
+
     // Updates a Realm to a given schema, using the Realm's pre-set schema mode.
     void update_schema(Schema schema, uint64_t version=0,
                        MigrationFunction migration_function=nullptr,

+ 98 - 3
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/realm.cpp

@@ -33,6 +33,7 @@
 #include "impl/realm_coordinator.hpp"
 
 #include <realm/group.hpp>
+#include <realm/util/scope_exit.hpp>
 
 namespace realm {
 class TestHelper {
@@ -175,10 +176,7 @@ TEST_CASE("SharedRealm: get_shared_realm()") {
         realm::util::remove_dir(config.path + ".note");
         realm::util::remove_dir_recursive(fallback_dir);
     }
-#endif
 
-// Windows doesn't use fifos
-#ifndef _WIN32
     SECTION("automatically append dir separator to end of fallback path") {
         std::string fallback_dir = tmp_dir() + "/fallback";
         realm::util::try_make_dir(fallback_dir);
@@ -446,6 +444,103 @@ TEST_CASE("SharedRealm: get_shared_realm()") {
     }
 }
 
+TEST_CASE("SharedRealm: get_shared_realm() with callback") {
+    TestFile local_config;
+    local_config.schema_version = 1;
+    local_config.schema = Schema{
+        {"object", {
+            {"value", PropertyType::Int}
+        }},
+    };
+
+    SECTION("immediately invokes callback for non-sync realms") {
+        bool called = false;
+        Realm::get_shared_realm(local_config, [&](auto realm, auto error) {
+            REQUIRE(realm);
+            REQUIRE(!error);
+            called = true;
+        });
+        REQUIRE(called);
+    }
+
+#if REALM_ENABLE_SYNC
+    if (!util::EventLoop::has_implementation())
+        return;
+
+    auto cleanup = util::make_scope_exit([=]() noexcept { SyncManager::shared().reset_for_testing(); });
+    SyncManager::shared().configure(tmp_dir(), SyncManager::MetadataMode::NoEncryption);
+
+    SyncServer server;
+    SyncTestFile config(server, "default");
+    config.cache = false;
+    config.schema = Schema{
+        {"object", {
+            {"value", PropertyType::Int},
+        }},
+    };
+    SyncTestFile config2(server, "default");
+    config2.cache = false;
+    config2.schema = config.schema;
+
+    SECTION("can open synced Realms that don't already exist") {
+        std::atomic<bool> called{false};
+        Realm::get_shared_realm(config, [&](auto realm, auto error) {
+            REQUIRE(realm);
+            REQUIRE(!error);
+            called = true;
+
+            REQUIRE(realm->read_group().get_table("class_object"));
+        });
+        util::EventLoop::main().run_until([&]{ return called.load(); });
+        REQUIRE(called);
+    }
+
+    SECTION("downloads Realms which exist on the server") {
+        {
+            auto realm = Realm::get_shared_realm(config2);
+            realm->begin_transaction();
+            sync::create_object(realm->read_group(), *realm->read_group().get_table("class_object"));
+            realm->commit_transaction();
+            wait_for_upload(*realm);
+        }
+
+        std::atomic<bool> called{false};
+        Realm::get_shared_realm(config, [&](auto realm, auto error) {
+            REQUIRE(realm);
+            REQUIRE(!error);
+            called = true;
+
+            REQUIRE(realm->read_group().get_table("class_object")->size() == 1);
+        });
+        util::EventLoop::main().run_until([&]{ return called.load(); });
+        REQUIRE(called);
+    }
+
+    SECTION("downloads latest state for Realms which already exist locally") {
+        wait_for_upload(*Realm::get_shared_realm(config));
+
+        {
+            auto realm = Realm::get_shared_realm(config2);
+            realm->begin_transaction();
+            sync::create_object(realm->read_group(), *realm->read_group().get_table("class_object"));
+            realm->commit_transaction();
+            wait_for_upload(*realm);
+        }
+
+        std::atomic<bool> called{false};
+        Realm::get_shared_realm(config, [&](auto realm, auto error) {
+            REQUIRE(realm);
+            REQUIRE(!error);
+            called = true;
+
+            REQUIRE(realm->read_group().get_table("class_object")->size() == 1);
+        });
+        util::EventLoop::main().run_until([&]{ return called.load(); });
+        REQUIRE(called);
+    }
+#endif
+}
+
 TEST_CASE("SharedRealm: notifications") {
     if (!util::EventLoop::has_implementation())
         return;

+ 9 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/results.cpp

@@ -2888,6 +2888,15 @@ TEST_CASE("results: set property value on all objects", "[batch_updates]") {
         realm->cancel_transaction();
     }
 
+    SECTION("set property values removes object from Results") {
+        realm->begin_transaction();
+        Results results(realm, table->where().equal(2,0));
+        CHECK(results.size() == 2);
+        r.set_property_value(ctx, "int", util::Any(INT64_C(42)));
+        CHECK(results.size() == 0);
+        realm->cancel_transaction();
+    }
+
     SECTION("set property value") {
         realm->begin_transaction();
 

+ 116 - 0
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/schema.cpp

@@ -17,6 +17,7 @@
 ////////////////////////////////////////////////////////////////////////////
 
 #include "catch.hpp"
+#include "util/test_file.hpp"
 
 #include "object_schema.hpp"
 #include "object_store.hpp"
@@ -84,6 +85,33 @@ struct StringMaker<SchemaChange> {
     REQUIRE_THROWS_WITH(expr, Catch::Matchers::Contains(msg))
 
 TEST_CASE("ObjectSchema") {
+
+    SECTION("Aliases are still present in schema returned from the Realm") {
+        TestFile config;
+        config.schema_version = 1;
+        config.schema = Schema{
+                {"object", {
+                   {"value", PropertyType::Int, Property::IsPrimary{false}, Property::IsIndexed{false}, "alias"}
+               }},
+        };
+
+        auto realm = Realm::get_shared_realm(config);
+        REQUIRE(realm->schema().find("object")->property_for_name("value")->public_name == "alias");
+    }
+
+    SECTION("looking up properties by alias matches name if alias is not set") {
+        auto schema = Schema{
+            {"object", {
+               {"value", PropertyType::Int, Property::IsPrimary{false}, Property::IsIndexed{false}, "alias"},
+               {"other_value", PropertyType::Int, Property::IsPrimary{false}, Property::IsIndexed{false}}
+            }},
+        };
+
+        REQUIRE(schema.find("object")->property_for_public_name("value") == nullptr);
+        REQUIRE(schema.find("object")->property_for_public_name("alias")->name == "value");
+        REQUIRE(schema.find("object")->property_for_public_name("other_value")->name == "other_value");
+    }
+
     SECTION("from a Group") {
         Group g;
         TableRef pk = g.add_table("pk");
@@ -531,6 +559,94 @@ TEST_CASE("Schema") {
                 "- Type 'object1' appears more than once in the schema.\n"
                 "- Type 'object2' appears more than once in the schema.");
         }
+
+        SECTION("rejects properties with the same name") {
+            Schema schema = {
+                {"object", {
+                    {"child", PropertyType::Object|PropertyType::Nullable, "object"},
+                    {"parent", PropertyType::Int},
+                    {"field1", PropertyType::Int},
+                    {"field2", PropertyType::String},
+                    {"field1", PropertyType::String},
+                    {"field2", PropertyType::String},
+                    {"field1", PropertyType::Int},
+                }, {
+                    {"parent", PropertyType::Array|PropertyType::LinkingObjects, "object", "child"}
+                }}
+            };
+
+            REQUIRE_THROWS_CONTAINING(schema.validate(),
+                  "- Property 'field1' appears more than once in the schema for type 'object'.\n"
+                  "- Property 'field2' appears more than once in the schema for type 'object'.\n"
+                  "- Property 'parent' appears more than once in the schema for type 'object'.");
+        }
+
+        SECTION("rejects schema if all properties have the same name") {
+            Schema schema = {
+                {"object", {
+                    {"field", PropertyType::Int},
+                    {"otherField", PropertyType::Int},
+                    {"field", PropertyType::Int},
+                    {"otherField", PropertyType::Int},
+                    {"field", PropertyType::Int},
+                    {"otherField", PropertyType::Int},
+                    {"field", PropertyType::Int},
+                    {"otherField", PropertyType::Int},
+                    {"field", PropertyType::Int},
+                    {"otherField", PropertyType::Int},
+                }}
+            };
+
+            REQUIRE_THROWS_CONTAINING(schema.validate(),
+                    "- Property 'field' appears more than once in the schema for type 'object'.\n"
+                    "- Property 'otherField' appears more than once in the schema for type 'object'.");
+        }
+
+        SECTION("rejects properties with the same alias") {
+            Schema schema = {
+                {"object", {
+                    {"child", PropertyType::Object|PropertyType::Nullable, "object"},
+
+                    // Alias == Name on computed property
+                    {"parentA", PropertyType::Int, Property::IsPrimary{false}, Property::IsIndexed{false}, "_parent"},
+
+                    // Name == Alias on other property
+                    {"fieldA", PropertyType::Int, Property::IsPrimary{false}, Property::IsIndexed{false}, "_field1"},
+                    {"fieldB", PropertyType::String, Property::IsPrimary{false}, Property::IsIndexed{false}, "_field2"},
+                    {"fieldC", PropertyType::String, Property::IsPrimary{false}, Property::IsIndexed{false}, "_field1"},
+                    {"fieldD", PropertyType::String, Property::IsPrimary{false}, Property::IsIndexed{false}, "_field2"},
+                    {"fieldE", PropertyType::Int, Property::IsPrimary{false}, Property::IsIndexed{false}, "_field1"},
+
+                    // Name == Alias
+                    {"fieldF", PropertyType::Int, Property::IsPrimary{false}, Property::IsIndexed{false}, "fieldF"},
+                }, {
+                    // Computed property alias == name on persisted property
+                    {"parentB", PropertyType::Array|PropertyType::LinkingObjects, "object", "child", "_parent"}
+                }}
+            };
+
+            REQUIRE_THROWS_CONTAINING(schema.validate(),
+                  "- Alias '_field1' appears more than once in the schema for type 'object'.\n"
+                  "- Alias '_field2' appears more than once in the schema for type 'object'.\n"
+                  "- Alias '_parent' appears more than once in the schema for type 'object'.");
+        }
+
+        SECTION("rejects properties whose name conflicts with an alias for another property") {
+            Schema schema = {
+                {"object", {
+                    {"child", PropertyType::Object|PropertyType::Nullable, "object"},
+                    {"field1", PropertyType::Int, Property::IsPrimary{false}, Property::IsIndexed{false}, "field2"},
+                    {"field2", PropertyType::Int, Property::IsPrimary{false}, Property::IsIndexed{false}, "parent"},
+                }, {
+                    {"parent", PropertyType::Array|PropertyType::LinkingObjects, "object", "child", "field1"}
+                }}
+            };
+
+            REQUIRE_THROWS_CONTAINING(schema.validate(),
+                  "- Property 'object.parent' has an alias 'field1' that conflicts with a property of the same name.\n"
+                  "- Property 'object.field1' has an alias 'field2' that conflicts with a property of the same name.\n"
+                  "- Property 'object.field2' has an alias 'parent' that conflicts with a property of the same name.");
+        }
     }
 
     SECTION("compare()") {

+ 1 - 1
Carthage/Checkouts/realm-cocoa/Realm/ObjectStore/tests/transaction_log_parsing.cpp

@@ -67,7 +67,7 @@ public:
         }
 
         validate(c);
-        return c;
+        return std::move(c);
     }
 
     explicit operator bool() const { return m_realm->is_in_transaction(); }

+ 4 - 0
Carthage/Checkouts/realm-cocoa/Realm/RLMProperty.mm

@@ -92,6 +92,10 @@ static bool rawTypeShouldBeTreatedAsComputedProperty(NSString *rawType) {
     if (is_array(prop.type)) {
         ret->_array = true;
     }
+    if (!prop.public_name.empty()) {
+        ret->_columnName = ret->_name;
+        ret->_name = @(prop.public_name.c_str());
+    }
     return ret;
 }
 

+ 1 - 1
Carthage/Checkouts/realm-cocoa/Realm/RLMRealm+Sync.mm

@@ -47,7 +47,7 @@ using namespace realm;
 
         Holder(partial_sync::Subscription&& s) : subscription(std::move(s)) { }
     };
-    auto state = std::make_shared<Holder>(partial_sync::subscribe(Results(_realm, std::move(q)), util::none));
+    auto state = std::make_shared<Holder>(partial_sync::subscribe(Results(_realm, std::move(q)), {}));
     state->token = state->subscription.add_notification_callback([=]() mutable {
         if (!callback) {
             return;

+ 3 - 0
Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager.h

@@ -110,6 +110,9 @@ typedef void(^RLMSyncErrorReportingBlock)(NSError *, RLMSyncSession * _Nullable)
 
 /**
  Extra HTTP headers to append to every request to a Realm Object Server.
+
+ Modifying this property while sync sessions are active will result in all
+ sessions disconnecting and reconnecting using the new headers.
  */
 @property (nullable, nonatomic, copy) NSDictionary<NSString *, NSString *> *customRequestHeaders;
 

+ 15 - 0
Carthage/Checkouts/realm-cocoa/Realm/RLMSyncManager.mm

@@ -138,6 +138,21 @@ static RLMSyncManager *s_sharedManager = nil;
     _userAgent = userAgent;
 }
 
+- (void)setCustomRequestHeaders:(NSDictionary<NSString *,NSString *> *)customRequestHeaders {
+    _customRequestHeaders = customRequestHeaders.copy;
+
+    for (auto&& user : SyncManager::shared().all_logged_in_users()) {
+        for (auto&& session : user->all_sessions()) {
+            auto config = session->config();
+            config.custom_http_headers.clear();;
+            for (NSString *key in customRequestHeaders) {
+                config.custom_http_headers.emplace(key.UTF8String, customRequestHeaders[key].UTF8String);
+            }
+            session->update_configuration(std::move(config));
+        }
+    }
+}
+
 #pragma mark - Passthrough properties
 
 - (RLMSyncLogLevel)logLevel {

+ 3 - 1
Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSession.mm

@@ -109,7 +109,9 @@ static RLMSyncConnectionState convertConnectionState(SyncSession::ConnectionStat
         // No need to save the token as RLMSyncSession always outlives the
         // underlying SyncSession
         session->register_connection_change_callback([=](auto, auto newState) {
-            self.connectionState = convertConnectionState(newState);
+            dispatch_async(dispatch_get_main_queue(), ^{
+                self.connectionState = convertConnectionState(newState);
+            });
         });
         return self;
     }

+ 162 - 0
Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSubscription.h

@@ -92,6 +92,63 @@ typedef RLM_CLOSED_ENUM(NSInteger, RLMSyncSubscriptionState) {
  */
 @property (nonatomic, readonly, nullable) NSError *error;
 
+/**
+ The raw query which this subscription is running on the server.
+
+ This string is a serialized representation of the RLMResults which the
+ subscription was created from. This representation does *not* use NSPredicate
+ syntax, and is not guaranteed to remain consistent between versions of Realm.
+ Any use of this other than manual inspection when debugging is likely to be
+ incorrect.
+
+ This is `nil` while the subscription is in the Creating state.
+ */
+@property (nonatomic, readonly, nullable) NSString *query;
+
+/**
+ When this subscription was first created.
+
+ This value will be `nil` for subscriptions created with older versions of Realm
+ which did not store the creation date. Newly created subscriptions should
+ always have a non-nil creation date.
+ */
+@property (nonatomic, readonly, nullable) NSDate *createdAt;
+
+/**
+ When this subscription was last updated.
+
+ This value will be `nil` for subscriptions created with older versions of Realm
+ which did not store the update date. Newly created subscriptions should
+ always have a non-nil update date.
+
+ The update date is the time when the subscription was last updated by a call
+ to `-[RLMResults subscribeWithOptions:]`, and not when the set of objects which
+ match the subscription last changed.
+ */
+@property (nonatomic, readonly, nullable) NSDate *updatedAt;
+
+/**
+ When this subscription will be automatically removed.
+
+ If the `timeToLive` parameter is set when creating a sync subscription, the
+ subscription will be automatically removed the first time that any subscription
+ is created, modified, or deleted after that time has elapsed.
+
+ This property will be `nil` if the `timeToLive` option was not enabled.
+ */
+@property (nonatomic, readonly, nullable) NSDate *expiresAt;
+
+/**
+ How long this subscription will persist after last being updated.
+
+ If the `timeToLive` parameter is set when creating a sync subscription, the
+ subscription will be automatically removed the first time that any subscription
+ is created, modified, or deleted after that time has elapsed.
+
+ This property will be NaN if the `timeToLive` option was not enabled.
+ */
+@property (nonatomic, readonly) NSTimeInterval timeToLive;
+
 /**
  Remove this subscription.
 
@@ -121,6 +178,82 @@ typedef RLM_CLOSED_ENUM(NSInteger, RLMSyncSubscriptionState) {
 
 @end
 
+/**
+ Configuration options for query-based sync subscriptions.
+ */
+@interface RLMSyncSubscriptionOptions : NSObject
+/**
+ The name of the subscription.
+
+ Naming a subscription makes it possible to look up a subscription by name
+ (using `-[RLMRealm subscriptionWithName:]`) or update an existing
+ subscription rather than creating a new one.
+ */
+@property (nonatomic, copy, nullable) NSString *name;
+
+/**
+ Whether this should update an existing subscription with the same name.
+
+ By default trying to create a subscription with a name that's already in use
+ will fail unless the new subscription is an exact match for the existing one.
+ If this is set to YES, instead the existing subscription will be updated using
+ the query and options from the new subscription. This only works if the new
+ subscription is for the same type of objects as the existing subscription.
+ Trying to overwrite a subscription with a subscription of a different type of
+ objects will fail.
+
+ The `updatedAt` and (if `timeToLive` is used) `expiresAt` properties are
+ updated whenever a subscription is overwritten even if nothing else has changed.
+ */
+@property (nonatomic) BOOL overwriteExisting;
+
+/**
+ How long (in seconds) a subscription should persist after being created.
+
+ By default subscriptions are persistent, and last until they are explicitly
+ removed by calling `unsubscribe()`. Subscriptions can instead be made temporary
+ by setting the time to live to how long the subscription should remain. After
+ that time has elapsed the subscription will be automatically removed.
+
+ A time to live of 0 or less disables subscription expiration.
+ */
+@property (nonatomic) NSTimeInterval timeToLive;
+
+/**
+ The maximum number of top-level matches to include in this subscription.
+
+ If more top-level objects than the limit match the query, only the first
+ `limit` objects will be included. This respects the sort and distinct order of
+ the query being subscribed to for the determination of what the "first" objects
+ are.
+
+ The limit does not count or apply to objects which are added indirectly due to
+ being linked to by the objects in the subscription or due to being listed in
+ `includeLinkingObjectProperties`. If the limit is larger than the number of
+ objects which match the query, all objects will be included. A limit of zero is
+ treated as unlimited.
+ */
+@property (nonatomic) NSUInteger limit;
+
+/**
+ Which RLMLinkingObjects properties should be included in the subscription.
+
+ Outgoing links (i.e. `RLMArray` and `RLMObject` properties) are automatically
+ included in sync subscriptions. That is, if you subscribe to a query which
+ matches one object, every object which is reachable via links from that object
+ are also included in the subscription.
+
+ By default, RLMLinkingObjects properties do not work this way. Instead, they
+ only report objects which happen to be included in a subscription. By naming
+ a RLMLinkingObjects property in this array, it can instead be treated as if
+ it was a RLMArray and include all objects which link to this object.
+
+ Any keypath which ends in a RLMLinkingObject property can be included in this
+ array, including ones involving intermediate links.
+ */
+@property (nonatomic, copy, nullable) NSArray<NSString *> *includeLinkingObjectProperties;
+@end
+
 /**
  Support for subscribing to the results of object queries in a synced Realm.
  */
@@ -214,6 +347,35 @@ typedef RLM_CLOSED_ENUM(NSInteger, RLMSyncSubscriptionState) {
  @see RLMSyncSubscription
  */
 - (RLMSyncSubscription *)subscribeWithName:(nullable NSString *)subscriptionName limit:(NSUInteger)limit;
+
+/**
+ Subscribe to a subset of the query represented by this `RLMResults`.
+
+ Subscribing to a query asks the server to synchronize all objects to the
+ client which match the query, along with all objects which are reachable
+ from those objects via links. This happens asynchronously, and the local
+ client Realm may not immediately have all objects which match the query.
+ Observe the `state` property of the returned subscription object to be
+ notified of when the subscription has been processed by the server and
+ all objects matching the query are available.
+
+ Creating a new subscription with the same name and query as an existing
+ subscription will not create a new subscription, but instead will return
+ an object referring to the existing sync subscription. This means that
+ performing the same subscription twice followed by removing it once will
+ result in no subscription existing.
+
+ The newly created subscription will not be reported by
+ `-[RLMRealm subscriptions]` or `-[RLMRealm subscriptionWithName:]` until
+ `state` has transitioned from `RLMSyncSubscriptionStateCreating` to any of the
+ other states.
+
+ @param options The additional configuration options for the subscription.
+ @return The subscription.
+
+ @see RLMSyncSubscription
+ */
+- (RLMSyncSubscription *)subscribeWithOptions:(RLMSyncSubscriptionOptions *)options;
 @end
 
 /**

+ 177 - 13
Carthage/Checkouts/realm-cocoa/Realm/RLMSyncSubscription.mm

@@ -30,25 +30,94 @@
 
 using namespace realm;
 
+@implementation RLMSyncSubscriptionOptions
+@end
+
 @interface RLMSyncSubscription ()
 @property (nonatomic, readwrite) RLMSyncSubscriptionState state;
 @property (nonatomic, readwrite, nullable) NSError *error;
+@property (nonatomic, readwrite) NSString *query;
+@property (nonatomic, readwrite, nullable) NSDate *createdAt;
+@property (nonatomic, readwrite, nullable) NSDate *updatedAt;
+@property (nonatomic, readwrite, nullable) NSDate *expiresAt;
+@property (nonatomic, readwrite) NSTimeInterval timeToLive;
 @end
 
 @implementation RLMSyncSubscription {
     partial_sync::SubscriptionNotificationToken _token;
     util::Optional<partial_sync::Subscription> _subscription;
+    Object _obj;
     RLMRealm *_realm;
 }
 
-- (instancetype)initWithName:(NSString *)name results:(Results const&)results realm:(RLMRealm *)realm {
+static std::vector<LinkPathPart> parseKeypath(StringData keypath, Group const& group,
+                                              Schema const& schema, const ObjectSchema *objectSchema) {
+    auto check = [&](bool condition, const char* fmt, auto... args) {
+        if (!condition) {
+            throw std::invalid_argument(util::format("Invalid LinkingObjects inclusion from key path '%1': %2.",
+                                                     keypath, util::format(fmt, args...)));
+        }
+    };
+
+    const char* begin = keypath.data();
+    const char* end = keypath.data() + keypath.size();
+    check(begin != end, "missing property name");
+
+    std::vector<LinkPathPart> ret;
+    while (begin != end) {
+        auto sep = std::find(begin, end, '.');
+        check(sep != begin && sep + 1 != end, "missing property name");
+        StringData key(begin, sep - begin);
+        begin = sep + (sep != end);
+
+        auto prop = objectSchema->property_for_name(key);
+        check(prop, "property '%1.%2' does not exist", objectSchema->name, key);
+        check(prop->type == PropertyType::Object || prop->type == PropertyType::LinkingObjects,
+              "property '%1.%2' is of unsupported type '%3'",
+              objectSchema->name, key, string_for_property_type(prop->type));
+
+        objectSchema = &*schema.find(prop->object_type);
+
+        if (prop->type == PropertyType::Object) {
+            check(begin != end, "key path must end in a LinkingObjects property and '%1.%2' is of type '%3'",
+                  objectSchema->name, key, string_for_property_type(prop->type));
+            ret.emplace_back(prop->table_column);
+        }
+        else {
+            ret.emplace_back(objectSchema->property_for_name(prop->link_origin_property_name)->table_column,
+                             ObjectStore::table_for_object_type(group, objectSchema->name));
+        }
+    }
+    return ret;
+}
+
+- (instancetype)initWithOptions:(RLMSyncSubscriptionOptions *)options results:(Results const&)results realm:(RLMRealm *)realm {
     if (!(self = [super init]))
         return nil;
 
-    _name = [name copy];
+    _name = [options.name copy];
+    _timeToLive = NAN;
     _realm = realm;
+    _createdAt = _updatedAt = NSDate.date;
     try {
-        _subscription = partial_sync::subscribe(results, name ? util::make_optional<std::string>(name.UTF8String) : util::none);
+        partial_sync::SubscriptionOptions opt;
+        if (options.name) {
+            opt.user_provided_name = std::string(RLMStringDataWithNSString(options.name));
+        }
+        if (options.timeToLive > 0) {
+            opt.time_to_live_ms = options.timeToLive * 1000;
+        }
+        opt.update = options.overwriteExisting;
+        if (options.includeLinkingObjectProperties) {
+            std::vector<std::vector<LinkPathPart>> keypaths;
+            for (NSString *keyPath in options.includeLinkingObjectProperties) {
+                keypaths.push_back(parseKeypath(keyPath.UTF8String, realm.group,
+                                                realm->_realm->schema(),
+                                                &results.get_object_schema()));
+            }
+            opt.inclusions = IncludeDescriptor{*ObjectStore::table_for_object_type(realm.group, results.get_object_type()), keypaths};
+        }
+        _subscription = partial_sync::subscribe(options.limit ? results.limit(options.limit) : results, std::move(opt));
     }
     catch (std::exception const& e) {
         @throw RLMException(e);
@@ -56,9 +125,12 @@ using namespace realm;
     self.state = (RLMSyncSubscriptionState)_subscription->state();
     __weak auto weakSelf = self;
     _token = _subscription->add_notification_callback([weakSelf] {
-        auto self = weakSelf;
-        if (!self)
-            return;
+        RLMSyncSubscription *self;
+        @autoreleasepool {
+            self = weakSelf;
+            if (!self)
+                return;
+        }
 
         // Retrieve the current error and status. Update our properties only if the values have changed,
         // since clients use KVO to observe these properties.
@@ -91,6 +163,22 @@ using namespace realm;
                 self.state = status;
             }
         }
+
+        if (status != RLMSyncSubscriptionStateComplete) {
+            return;
+        }
+
+        auto obj = self->_subscription->result_set_object();
+        if (obj && obj->is_valid()) {
+            _obj = std::move(*obj);
+            _token = {};
+            _token.result_sets_token = _obj.add_notification_callback([weakSelf](CollectionChangeSet const&, std::exception_ptr) {
+                @autoreleasepool {
+                    [weakSelf updateFromRow];
+                }
+            });
+            [self updateFromRow];
+        }
     });
 
     return self;
@@ -99,6 +187,36 @@ using namespace realm;
 - (void)unsubscribe {
     partial_sync::unsubscribe(*_subscription);
 }
+
+- (void)updateFromRow {
+    // We only want to call the setter if the value actually changed because of KVO
+#define REALM_SET_IF_CHANGED(prop, value) do { \
+    auto newValue = value; \
+    if (prop != newValue) { \
+        prop = newValue; \
+    } \
+} while (0)
+
+    if (!_obj.is_valid()) {
+        REALM_SET_IF_CHANGED(self.state, RLMSyncSubscriptionStateInvalidated);
+        return;
+    }
+
+    auto row = _obj.row();
+    REALM_SET_IF_CHANGED(self.query, RLMStringDataToNSString(row.get_string(row.get_column_index("query"))));
+    REALM_SET_IF_CHANGED(self.createdAt, RLMTimestampToNSDate(row.get_timestamp(row.get_column_index("created_at"))));
+    REALM_SET_IF_CHANGED(self.updatedAt, RLMTimestampToNSDate(row.get_timestamp(row.get_column_index("updated_at"))));
+    REALM_SET_IF_CHANGED(self.expiresAt, RLMTimestampToNSDate(row.get_timestamp(row.get_column_index("expires_at"))));
+#undef REALM_SET_IF_CHANGED
+
+    auto ttl = row.get<util::Optional<int64_t>>(row.get_column_index("time_to_live"));
+    if (ttl && _timeToLive != *ttl / 1000.0) {
+        self.timeToLive = *ttl / 1000.0;
+    }
+    else if (!ttl && !isnan(_timeToLive)) {
+        self.timeToLive = NAN;
+    }
+}
 @end
 
 @interface RLMSyncSubscriptionObject : RLMObjectBase
@@ -112,6 +230,10 @@ using namespace realm;
     return _row.is_attached() ? RLMStringDataToNSString(_row.get_string(_row.get_column_index("name"))) : nil;
 }
 
+- (NSString *)query {
+    return _row.is_attached() ? RLMStringDataToNSString(_row.get_string(_row.get_column_index("query"))) : nil;
+}
+
 - (RLMSyncSubscriptionState)state {
     if (!_row.is_attached()) {
         return RLMSyncSubscriptionStateInvalidated;
@@ -132,6 +254,29 @@ using namespace realm;
                            userInfo:@{NSLocalizedDescriptionKey: RLMStringDataToNSString(err)}];
 }
 
+- (NSDate *)createdAt {
+    return _row.is_attached() ? RLMTimestampToNSDate(_row.get_timestamp(_row.get_column_index("created_at"))) : nil;
+}
+
+- (NSDate *)updatedAt {
+    return _row.is_attached() ? RLMTimestampToNSDate(_row.get_timestamp(_row.get_column_index("updated_at"))) : nil;
+}
+
+- (NSDate *)expiresAt {
+    return _row.is_attached() ? RLMTimestampToNSDate(_row.get_timestamp(_row.get_column_index("expires_at"))) : nil;
+}
+
+- (NSTimeInterval)timeToLive {
+    if (!_row.is_attached()) {
+        return NAN;
+    }
+    auto columnIndex = _row.get_column_index("time_to_live");
+    if (_row.is_null(columnIndex)) {
+        return NAN;
+    }
+    return _row.get_int(columnIndex) / 1000.0;
+}
+
 - (NSString *)descriptionWithMaxDepth:(NSUInteger)depth {
     if (depth == 0) {
         return @"<Maximum depth exceeded>";
@@ -139,10 +284,10 @@ using namespace realm;
 
     auto objectType = _row.get_string(_row.get_column_index("matches_property"));
     objectType = objectType.substr(0, objectType.size() - strlen("_matches"));
-    return [NSString stringWithFormat:@"RLMSyncSubscription {\n\tname = %@\n\tobjectType = %@\n\tquery = %@\n\tstatus = %@\n\terror = %@\n}",
+    return [NSString stringWithFormat:@"RLMSyncSubscription {\n\tname = %@\n\tobjectType = %@\n\tquery = %@\n\tstatus = %@\n\terror = %@\n\tcreatedAt = %@\n\tupdatedAt = %@\n\texpiresAt = %@\n\ttimeToLive = %@\n}",
             self.name, RLMStringDataToNSString(objectType),
             RLMStringDataToNSString(_row.get_string(_row.get_column_index("query"))),
-            @(self.state), self.error];
+            @(self.state), self.error, self.createdAt, self.updatedAt, self.expiresAt, @(self.timeToLive)];
 }
 
 - (void)unsubscribe {
@@ -183,12 +328,22 @@ using namespace realm;
 }
 @end
 
+static ObjectSchema& addPublicNames(ObjectSchema& os) {
+    using namespace partial_sync;
+    os.property_for_name(property_created_at)->public_name    = "createdAt";
+    os.property_for_name(property_updated_at)->public_name    = "updatedAt";
+    os.property_for_name(property_expires_at)->public_name    = "expiresAt";
+    os.property_for_name(property_time_to_live)->public_name  = "timeToLive";
+    os.property_for_name(property_error_message)->public_name = "error";
+    return os;
+}
+
 // RLMClassInfo stores pointers into the schema rather than owning the objects
 // it points to, so for a ClassInfo that's not part of the schema we need a
 // wrapper object that owns them
 RLMResultsSetInfo::RLMResultsSetInfo(__unsafe_unretained RLMRealm *const realm)
-: osObjectSchema(ObjectSchema(realm->_realm->read_group(), partial_sync::result_sets_type_name))
-, rlmObjectSchema([RLMObjectSchema objectSchemaForObjectStoreSchema:osObjectSchema])
+: osObjectSchema(realm->_realm->read_group(), partial_sync::result_sets_type_name)
+, rlmObjectSchema([RLMObjectSchema objectSchemaForObjectStoreSchema:addPublicNames(osObjectSchema)])
 , info(realm, rlmObjectSchema, &osObjectSchema)
 {
     rlmObjectSchema.accessorClass = [RLMSyncSubscriptionObject class];
@@ -231,15 +386,24 @@ RLMClassInfo& RLMResultsSetInfo::get(__unsafe_unretained RLMRealm *const realm)
 
 @implementation RLMResults (SyncSubscription)
 - (RLMSyncSubscription *)subscribe {
-    return [[RLMSyncSubscription alloc] initWithName:nil results:_results realm:self.realm];
+    return [[RLMSyncSubscription alloc] initWithOptions:nil results:_results realm:self.realm];
 }
 
 - (RLMSyncSubscription *)subscribeWithName:(NSString *)subscriptionName {
-    return [[RLMSyncSubscription alloc] initWithName:subscriptionName results:_results realm:self.realm];
+    auto options = [[RLMSyncSubscriptionOptions alloc] init];
+    options.name = subscriptionName;
+    return [[RLMSyncSubscription alloc] initWithOptions:options results:_results realm:self.realm];
 }
 
 - (RLMSyncSubscription *)subscribeWithName:(NSString *)subscriptionName limit:(NSUInteger)limit {
-    return [[RLMSyncSubscription alloc] initWithName:subscriptionName results:_results.limit(limit) realm:self.realm];
+    auto options = [[RLMSyncSubscriptionOptions alloc] init];
+    options.name = subscriptionName;
+    options.limit = limit;
+    return [[RLMSyncSubscription alloc] initWithOptions:options results:_results realm:self.realm];
+}
+
+- (RLMSyncSubscription *)subscribeWithOptions:(RLMSyncSubscriptionOptions *)options {
+    return [[RLMSyncSubscription alloc] initWithOptions:options results:_results realm:self.realm];
 }
 @end
 

+ 2 - 2
Carthage/Checkouts/realm-cocoa/Realm/Realm-Info.plist

@@ -17,11 +17,11 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>3.14.1</string>
+	<string>3.15.0</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>
-	<string>3.14.1</string>
+	<string>3.15.0</string>
 	<key>NSHumanReadableCopyright</key>
 	<string>Copyright © 2014 Realm. All rights reserved.</string>
 	<key>NSPrincipalClass</key>

+ 3 - 2
Carthage/Checkouts/realm-cocoa/Realm/Tests/InterprocessTests.m

@@ -118,8 +118,9 @@
 
 - (void)testCompactOnLaunchFailSilently {
     if (self.isParent) {
-        [[RLMRealm defaultRealm] transactionWithBlock:^{}];
+        RLMRealm *realm  = [RLMRealm defaultRealm];
         RLMRunChildAndWait(); // runs the event loop
+        (void)[realm configuration]; // ensure the Realm stays open while the child process runs
     } else {
         unsigned long long (^fileSize)(NSString *) = ^unsigned long long(NSString *path) {
             NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
@@ -136,7 +137,7 @@
         unsigned long long sizeBefore = fileSize(config.fileURL.path);
         RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];
         unsigned long long sizeAfter = fileSize(config.fileURL.path);
-        XCTAssertEqual(sizeBefore, sizeAfter);
+        XCTAssertLessThanOrEqual(sizeBefore, sizeAfter);
         XCTAssertTrue(realm.isEmpty);
         XCTAssertTrue(blockCalled);
     }

+ 13 - 50
Carthage/Checkouts/realm-cocoa/build.sh

@@ -126,7 +126,7 @@ xc() {
 }
 
 xctest() {
-  xc "$@" build
+  xc "$@" build-for-testing
   xc "$@" test
 }
 
@@ -157,11 +157,7 @@ build_combined() {
         fi
     elif [[ "$os" == "appletvos"  ]]; then
         os_name="tvos"
-        if (( $(xcode_version_major) >= 9 )); then
-            destination="Apple TV"
-        else
-            destination="Apple TV 1080p"
-        fi
+        destination="Apple TV"
     fi
 
     # Derive build paths
@@ -227,17 +223,7 @@ move_to_clean_dir() {
 
 test_ios_static() {
     destination="$1"
-    xc "-scheme 'Realm iOS static' -configuration $CONFIGURATION -sdk iphonesimulator -destination '$destination' build"
-    if (( $(xcode_version_major) < 9 )); then
-        xc "-scheme 'Realm iOS static' -configuration $CONFIGURATION -sdk iphonesimulator -destination '$destination' test 'ARCHS=\$(ARCHS_STANDARD_32_BIT)'"
-    fi
-
-    # Xcode's depending tracking is lacking and it doesn't realize that the Realm static framework's static library
-    # needs to be recreated when the active architectures change. Help Xcode out by removing the static library.
-    settings=$(xcode "-scheme 'Realm iOS static' -configuration $CONFIGURATION -sdk iphonesimulator -destination '$destination' -showBuildSettings")
-    path=$(echo "$settings" | awk '/CONFIGURATION_BUILD_DIR/ { cbd = $3; } /EXECUTABLE_PATH/ { ep = $3; } END { printf "%s/%s\n", cbd, ep; }')
-    rm "$path"
-
+    xc "-scheme 'Realm iOS static' -configuration $CONFIGURATION -sdk iphonesimulator -destination '$destination' build-for-testing"
     xc "-scheme 'Realm iOS static' -configuration $CONFIGURATION -sdk iphonesimulator -destination '$destination' test"
 }
 
@@ -612,19 +598,13 @@ case "$COMMAND" in
         ;;
 
     "test-ios-dynamic")
-        xc "-scheme Realm -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' build"
-        if (( $(xcode_version_major) < 9 )); then
-            xc "-scheme Realm -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' test 'ARCHS=\$(ARCHS_STANDARD_32_BIT)'"
-        fi
+        xc "-scheme Realm -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' build-for-testing"
         xc "-scheme Realm -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' test"
         exit 0
         ;;
 
     "test-ios-swift")
-        xc "-scheme RealmSwift -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' build"
-        if (( $(xcode_version_major) < 9 )); then
-            xc "-scheme RealmSwift -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' test 'ARCHS=\$(ARCHS_STANDARD_32_BIT)'"
-        fi
+        xc "-scheme RealmSwift -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' build-for-testing"
         xc "-scheme RealmSwift -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' test"
         exit 0
         ;;
@@ -648,21 +628,13 @@ case "$COMMAND" in
         ;;
 
     "test-tvos")
-        if (( $(xcode_version_major) >= 9 )); then
-            destination="Apple TV"
-        else
-            destination="Apple TV 1080p"
-        fi
+        destination="Apple TV"
         xctest "-scheme Realm -configuration $CONFIGURATION -sdk appletvsimulator -destination 'name=$destination'"
         exit $?
         ;;
 
     "test-tvos-swift")
-        if (( $(xcode_version_major) >= 9 )); then
-            destination="Apple TV"
-        else
-            destination="Apple TV 1080p"
-        fi
+        destination="Apple TV"
         xctest "-scheme RealmSwift -configuration $CONFIGURATION -sdk appletvsimulator -destination 'name=$destination'"
         exit $?
         ;;
@@ -766,7 +738,6 @@ case "$COMMAND" in
 
     "verify-osx")
         sh build.sh test-osx
-        sh build.sh analyze-osx
         sh build.sh examples-osx
 
         (
@@ -910,11 +881,7 @@ case "$COMMAND" in
 
     "examples-tvos")
         workspace="examples/tvos/objc/RealmExamples.xcworkspace"
-        if (( $(xcode_version_major) >= 9 )); then
-            destination="Apple TV"
-        else
-            destination="Apple TV 1080p"
-        fi
+        destination="Apple TV"
 
         xc "-workspace $workspace -scheme DownloadCache -configuration $CONFIGURATION -destination 'name=$destination' build ${CODESIGN_PARAMS}"
         xc "-workspace $workspace -scheme PreloadedData -configuration $CONFIGURATION -destination 'name=$destination' build ${CODESIGN_PARAMS}"
@@ -927,12 +894,7 @@ case "$COMMAND" in
             workspace="${workspace/swift/swift-$REALM_XCODE_VERSION}"
         fi
 
-        if (( $(xcode_version_major) >= 9 )); then
-            destination="Apple TV"
-        else
-            destination="Apple TV 1080p"
-        fi
-
+        destination="Apple TV"
         xc "-workspace $workspace -scheme DownloadCache -configuration $CONFIGURATION -destination 'name=$destination' build ${CODESIGN_PARAMS}"
         xc "-workspace $workspace -scheme PreloadedData -configuration $CONFIGURATION -destination 'name=$destination' build ${CODESIGN_PARAMS}"
         exit 0
@@ -1228,7 +1190,7 @@ EOM
 
     package-*-swift)
         PLATFORM=$(echo $COMMAND | cut -d - -f 2)
-        for version in 9.2 9.3 9.4 10.0 10.1 10.2; do
+        for version in 9.2 9.3 9.4 10.0 10.1 10.2.1; do
             REALM_XCODE_VERSION=$version
             REALM_SWIFT_VERSION=
             set_xcode_and_swift_versions
@@ -1237,7 +1199,7 @@ EOM
         done
 
         cd build/$PLATFORM
-        zip --symlinks -r realm-swift-framework-$PLATFORM.zip swift-9.2 swift-9.2 swift-9.4 swift-10.0 swift-10.1 swift-10.2
+        zip --symlinks -r realm-swift-framework-$PLATFORM.zip swift-9.2 swift-9.2 swift-9.4 swift-10.0 swift-10.1 swift-10.2.1
         ;;
 
     package-*-swift-*)
@@ -1441,8 +1403,9 @@ x.y.z Release notes (yyyy-MM-dd)
 
 ### Compatibility
 * File format: Generates Realms with format v9 (Reads and upgrades all previous formats)
-* Realm Object Server: 3.11.0 or later.
+* Realm Object Server: 3.21.0 or later.
 * APIs are backwards compatible with all previous releases in the 3.x.y series.
+* Carthage release for Swift is built with Xcode 10.2.1.
 EOS)
         changelog=$(cat CHANGELOG.md)
         echo "$empty_section" > CHANGELOG.md

+ 4 - 4
Carthage/Checkouts/realm-cocoa/dependencies.list

@@ -1,4 +1,4 @@
-VERSION=3.14.1
-REALM_CORE_VERSION=5.14.0
-REALM_SYNC_VERSION=3.15.1
-REALM_OBJECT_SERVER_VERSION=3.13.1
+VERSION=3.15.0
+REALM_CORE_VERSION=5.19.1
+REALM_SYNC_VERSION=4.4.2
+REALM_OBJECT_SERVER_VERSION=3.21.1

+ 1 - 0
iOSClient/Library/OCCommunicationLib/OCSharedDto.h

@@ -51,6 +51,7 @@ typedef enum {
 @property (nonatomic, copy) NSString *token;
 @property NSInteger storage;
 @property NSInteger mailSend;
+@property (nonatomic, copy) NSString *url;
 @property (nonatomic, copy) NSString *uidOwner;
 @property (nonatomic, copy) NSString *shareWithDisplayName;
 @property (nonatomic, copy) NSString *displayNameOwner;

Some files were not shown because too many files changed in this diff